原题翻译
注意到123456789这个九位数字是由1到9的数字组成的,并且没有重复。翻倍后得到246913578,又一次得到了一个九位数字 ,也一样由1到9的数字组成,只不过排列方式有所不同。再翻倍一下啊看看会得到什么结果吧!
现在你应该利用这个性质,去多检查一下其他的数吧!也就是,翻倍一个给定的k位的数值,看看翻倍后的结果是不是由初始的数打乱排列后重新组成。
输入的要求:
每次输入一个测试案例,每个输入案例是正整数且位数不超过二十位。
输出的要求:
对于每个输入,如果输出的结果,是由初始输入的每位数字的重新组成,那么第一行输出"Yes",如果不是就"No",在第二行输出翻倍之后的结果。
Sample Input:
1234567899
Sample Output:
Yes
2469135798
感想 :
原本不太想写的,因为代码的思路主要是借鉴的别人,但是好记性不如烂笔头,而且有新的知识点(模拟乘法)。就再写一遍好了,会加上自己的详细注释。
思路:(模拟乘法)
对于这道题,数值太大了,二十位的数字。我一开始想的比较简单,因为没有做过大数的题目,我就想着用long型来保存输入,对输入做处理。结果显而易见,当输入的数值超过了long型长度之后,超过的位数上的数就不会被读取进去,结果处理完自然是错。
对于这道题,应该用字符数组比如:char input[ ] 来保存输入。数组的大小,就选择25就行了,事实上超过20就行
对于输入的这个char型数组,我们要将他每一位从低到高保存在一个新的int型数组中,我将它命名为d1[ ], 紧接着,对这个d1[ ],做模拟乘法的操作,并且将结果从低到高的保存在d2[ ] 之中。这d1 和d2数组,保存着我们的结果,我们可以创建两个数组
(我命名为checkdigit1 [ 10 ] checkdigit2 [10] ),分别检查d1 d2数组保存的数字的个数,如果个数相同我就输出yes不同我就输出No
上面是主要的思路,进去之后还要考虑的细枝末节,将在代码中呈现出来。
接下来我会按照我的思路,一点点写完代码,一段一段完成。
#include<stdio.h>
#include<string.h>
int main(){
char input[25];
int d1[25]={0};d2[25]={0};
int checkdigit1[10]={0},checkdigit2[10]={0};
while(scanf("%s",input) != EOF)//循环驱动条件,依照我的理解来说是,会让我们每次输入都经过一次循环,输入就是循环的条件
{
int len = strlen(input);//调用字符串函数,得到输入的数的位数。
int i;
for(i=0;i<len;i++){
//将从低位到高位赋值。
d1[i]=input[len-1-i]-'0';// input[]-‘0’其实就是做ascii码数值的相减。12345.。。。这些数字在ascii都是相邻的,比如‘1’-‘0’=1利用这个性质,赋值int数组
}
doubleA() ;
}
return 0;
}
处理完d1数组,接下来我要将翻倍结果保存在d2数组中,我写了一个doubleA函数,参数表里面要有什么呢? 要有要处理的d1,要改变结果的d2。模拟乘法是怎么样的?
下图举了两个例子 一个存在进位carry , 一个不存在。我要做的就是这样,途中881 ,123就是d1 数组的数。低位乘以2的余数保存在对应的d2数组单元中。并且我会用一个carry 变量来保存进位。

doubleA的函数大概是这样:
void doubleA(int a[],int alen,int b[],int blen,int *isok) {
int carry=0;
int i;
for(i=0;i<alen;i++){
b[i]=(2*a[i]+carry)%10;
carry=(2*a[i]+carry)/10;
}
if(carry){
b[i]=carry;
*isok=0;
}
}
参数表里面,我除了引进了两个要做处理的数组,还引进了一个int 指针,是用于后面主函数做判断。发生了进位之后,比如我的输入是881,输出是1762,前后两者位数不一样,那肯定不符合题目要求,要输出NO的,所以我这里让isok=0,就是不太OK。因为题目要求,无论是yes还是NO都要输出翻倍的结果,所以这里也要把最后的进位保存下来,留待输出。
完整代码如下:
#include<stdio.h>
#include<string.h>
void doubleA(int a[],int alen,int b[],int blen,int *isok);
int main(){
char input[25];
int d1[25]={0},d2[25]={0};
int checkdigit1[10]={0},checkdigit2[10]={0};
int isok=1;//接下来会做两个判断会遇到变0的考验,通过证伪来达到想要的结果
while(scanf("%s",input) != EOF)//循环驱动条件,依照我的理解来说是,会让我们每次输入都经过一次循环,输入就是循环的条件
{
int len = strlen(input);//调用字符串函数,得到输入的数的位数。
int i;
for(i=0;i<len;i++){
//将从低位到高位赋值。
d1[i]=input[len-1-i]-'0'; // input[]-‘0’其实就是做ascii码数值的相减。12345.。。。这些数字在ascii都是相邻的,比如‘1’-‘0’=1利用这个性质,赋值int数组
}
doubleA(d1,len,d2,len,&isok);
if(isok){ //输出和输入的位数一致才做检测
for(i=0;i<10;i++){
checkdigit1[d1[i]]++;
checkdigit2[d2[i]]++;
}
// 用于记录d1、d2的0-9的个数
for(i=0;i<9;i++){
if( checkdigit1[i]!=checkdigit2[i] ){
isok=0;
break;
// 遍历check1 check2数组,上面若出现有个数不相同的情况就break,而且不OK。
}
}
}
if(isok){
printf("Yes\n");
}
else
{
printf("No\n");
}
if(d2[len]!=0)
printf("%d",d2[len]);
for(i=len-1;i>=0;i--){
printf("%d",d2[i]);
}
}
return 0;
}
void doubleA(int a[],int alen,int b[],int blen,int *flag) {
int carry=0;
int i;
for(i=0;i<alen;i++){
b[i]=(2*a[i]+carry)%10;
carry=(2*a[i]+carry)/10;
}
if(carry){
b[i]=carry;
*flag=0;
}
}
这篇博客讨论了一道编程题,该题要求检查翻倍一个给定的多位数后,其数字是否仍由原始数字组成。作者提到了使用字符数组存储输入,通过模拟乘法操作处理大数,并用额外的数组记录每位数字出现的次数以进行比较。在代码实现中,作者用C语言编写了一个doubleA函数来处理翻倍操作,并检查结果的位数和原始数字的位数是否一致。如果一致,则继续检查位数相同的条件下,每位数字出现的次数是否相同,从而判断是否输出Yes或No。
1772

被折叠的 条评论
为什么被折叠?



