7-49 Have Fun with Numbers (20 分)

题目:

Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!

Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.

Input Specification:

Each input contains one test case. Each case contains one positive integer with no more than 20 digits.

Output Specification:

For each test case, first print in a line "Yes" if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or "No" if not. Then in the next line, print the doubled number.

Sample Input:

1234567899

Sample Output:

Yes
2469135798

这里的位数较多,unsigned long long不够用,只能用数组了

这里使用scanf+字符数组

通过记录每一位的数字计数(解法一),也可以通过int数组下标0~9的对应的数表示这十个数字的出现次数(解法二)

解法一:

/*
输入一个数,将其乘二,如果结果是输入数字的各位数字的重组,则输出"Yes"否则输出"No"之后在下一行输出乘二的结果
输入的是不超过20位的正整数 
*/
#include <stdio.h>
int main()
{
    int i, flag[20]={0},flag2,j,t,jin,s;     
    /*flag[20]用来标记该位是否有数字(0),是否被找到(1) 	t用来标记输入的最小一位 	flag2表示该位是否找到*/ 
    char in[20],o[21];									//20位太大了只能用字符数组 
    jin=0;												//jin是进位标记位 
    s=1;												//s即start,打印数的时候从o[0]位还是从o[1]位开始 
    i=0;												//工具人 
    scanf("%c",&in[i]);
    while(in[i]<='9'&&in[i]>='0')
    {
        i++;
        scanf("%c",&in[i]);
    }
    in[i]='\0';
    t=--i;												//此时i=t=最后一位所在的位置
//  printf("t=%d",t);									//看下t的情况 应该是正确的 
//  for(i=0;i<=t;)
//  {
//      printf("in[i]=%c i=%d\n",in[i],i);				//打印出每一位 
//		i++;
//	}
	while(i>=0)											//开始一位一位乘以2 并进位 
	{
		int temp;
		temp=in[i]-'0';
//		printf("temp=%d ",temp);
		if(temp<=4)
		{
			o[i+1]=2*temp+'0'+jin;
			jin=0;									//进位标记位 
			s=1;									//好像是判断比赋值占资源 
		}
		else										//第一位大于4就是说直接进位,那就直接输出"No" 
		{
			o[i+1]=2*temp%10+'0'+jin;
			jin=1;
			s=0;
		}
		i--;
	}
	if(jin)						//如果最后需要进一位 
	{
		o[0]=1;					//最高位置1 
	}
	for(i=0;i<=t;i++)			//t这时候在in[]最后一个数字上
	{
		flag2=0;				//找每一位的时候都要置0,找到再置1
		if(jin)					//最高位需要进位 
		{
			o[0]='1';
//			printf("a");
			break;
		}
		for(j=1;j<=t+1;j++)
		{
			if(o[j]==in[i]&&flag[i]==0)
			{
				flag2=1;					//找到就置1 
				flag[i]=1;					//找过的一个in[]就标记
				break;
			}
//			printf("o[%d]=%c in[%d]=%c\n",j,o[j],i,in[i]);
		}
		if(flag2==0)				//没找到 
		{
			break;
		}
	}
	if(flag2==0)			//异常结束 即在允许找寻的位没找到或者最高位大于4 
	{
		printf("No\n");
	}
	else if(flag2==1)
	{
		printf("Yes\n");
	}
	for(i=s;i<=t+1;i++)				//从s位开始(如果最高位进位就是0否则是1) 
	{
		printf("%c",o[i]);			//正常打印两倍 
	}
    return 0;
}

解法二:

#include <stdio.h>
int dbanumber(int a[],char b[],int k);
/*
函数功能:
将一个装在char b[]里面的数乘二,如果最高位进位就返回-1,
没用完int a[]里面的数字就返回1;用完且不进位返回0
*/ 
int main(int argc,char argv[])
{
    int a[10]={0};                      //装各个数字个数的数组
    char b[20];                         //装输入数的字符组
    int i=0,num=0,flag=9;               //flag用来装函数的返回值
	do{
        scanf("%c",&b[i]);
		if(b[i]<='9'&&b[i]>='0')
		{
			a[b[i]-'0']++;              //输入一个数字i,该数字对应的a[i]加一
		}
		i++;
    }while(b[i-1]<='9'&&b[i-1]>='0');
    num=i-1;
    flag=dbanumber(&a[0],&b[0],i);
    if(flag==0)							//根据返回值打印结果 
    {
        printf("Yes\n");
    }
    else if(flag==1)
    {
        printf("No\n");
    }
    else if(flag==-1)					//这里的1是因为最高位发生进位 
    {
        printf("No\n1");
    }
    for(i=0;i<num;i++)					//把修改后的字符数组打印出来 
    {
        printf("%c",b[i]);
    }
    return 0;
}

int dbanumber(int a[],char b[],int k)         //将一个装在char b[]里面的数乘二,如果最高位进位就返回-1,没用完int a[]里面的数字就返回1;用完且不进位返回0
{
    int i,t,co,flag;
    flag=0;
    co=0;
    for(i=k-2;i>=0;i--)
    {
        t=b[i]-'0';
        t=t*2+co;				//t为乘二且进位后但未将十位进上去的该位的数 
        if(t>9)
        {
            t=t%10;             //co用来记录进到下一位的进位标记位 t用来记录此一位
            co=1;
        }
        else
        {
            co=0;
        }
        a[t]--;                 //数字t的数目对应的a[t]
        if(a[t]<0&&flag==0)		//此时发现多了某位上的数字 
		{
			flag=1;             //发现后就不需要再找了
		}
        b[i]=t+'0';             //
    }
    if(co)					//发现发生进位 
    {
        flag=-1;
    }
    return flag;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值