HDU ACM Steps:整数对

HDU ACM Steps:整数对

题目描述

Gardon和小希玩了一个游戏,Gardon随便想了一个数A(首位不能为0),把它去掉一个数字以后得到另外一个数B,他把A和B的和N告诉了小希,让小希猜想他原来想的数字。不过为了公平起见,如果小希回答的数虽然不是A,但同样能达到那个条件(去掉其中的一个数字得到B,A和B之和是N),一样算小希胜利。而且小希如果能答出多个符合条件的数字,就可以得到额外的糖果。
所以现在小希希望你编写一个程序,来帮助她找到尽可能多的解。
例如,Gardon想的是A=31,B=3 告诉小希N=34,
小希除了回答31以外还可以回答27(27+7=34)所以小希可以因此而得到一个额外的糖果

输入

输入包含多组数据,每组数据一行,包含一个数N(1<=N<=10^9),文件以0结尾

输出

对于每个输入的N,输出所有符合要求的解(按照大小顺序排列)如果没有这样的解,输出"No solution."

输入样例

34
152
21
0

输出样例

27 31 32
126 136 139 141
No solution.

思路

1.对于这种较大的数字的处理,一般是把它拆分成 a × 1 0 k + x × 1 0 k 1 + b a\times10^k+x\times10^{k-1}+b 的形式。
例如:一个有22位数的数字的最后一位为7,当它乘7时,得到的结果恰好仍为一个22位数,只不过末尾的7移到首位,其他21个数顺序没有发生变化,现在求这个22位数。
答案:设X为顺序排列的21个数字的值,则有 X × 10 + 7 = 7 1 0 21 + X X\times10+7=7*10^{21}+X
2.这道题也是这个方法,令 a n s = a × 1 0 k + x × 1 0 k 1 + b ans=a\times10^k+x\times10^{k-1}+b ,且 x x 是题目中去掉的数字。因此可以得到 n = a × 1 0 k + x × 1 0 k 1 + b + a + a × 1 0 k 1 + b n=(a\times10^k+x\times10^{k-1}+b+a)+a\times10^{k-1}+b ,化简可得: n = ( 11 a + x ) × 1 0 k 1 + 2 b n=(11a+x)\times10^{k-1}+2b .
因此通过下面三个式子枚举 k k 值就可以得到 a x b a、x、b 的值,从而得到 a n s ans
a=n/i/11; // i是10的k次方
x=n/i%11;
x=n/i%11;b=(n-x*i-a*i*11)/2;
3.仍需注意的是 2 b 2b 可能产生进位,这一个需要考虑,它会对 x x 产生影响,但是不会对 a a 有影响,因为 x x 本身最大为9,+1后最大为10,不会对 a=n/i/11;有影响。另外一个问题是, a a x x 不能同时为0,因为同时为0的话,我们取的k值,超过了答案的位数。例如当n=152时,k=3时,得到的一个结果是76,而这个答案显然是错误的。
4.把得到的答案放在数组里,最后排序输出,同时还要注意输出时要去重,因为不同的 k k 得到的答案可能一样,例如:n=12,k取1时,答案为11,k取2时,答案也是11.

代码

#include<stdio.h>
#include<cstring>
#include <algorithm>
using namespace std;
typedef long long LL;

LL n; 
LL ans[1000];//ans[0]计数 
LL a,x;
double b;
int main()
{
	while(scanf("%d",&n)&&n) 
	{
		memset(ans,0,sizeof(ans));//初始化
		for(int i=1;i<=n;i*=10)
		{
			a=n/i/11;
			x=n/i%11;
			
			b=(n-x*i-a*i*11)/2;
			if((11*a+x)*i+2*b==n&&a+x&&x<10) //x=10的话,肯定是发生进位
			   {
				ans[++ans[0]]=(10*a+x)*i+b;
			    }
			    
		    x--;//进位
			b=(n-x*i-a*i*11)/2;
			if((11*a+x)*i+2*b==n&&a+x&&x>=0) 
			   {
				ans[++ans[0]]=(10*a+x)*i+b;
			   }	
		}
		
		sort(ans+1,ans+1+ans[0]);
		if(!ans[0]) printf("No solution.\n");
		else
		{
			printf("%ld",ans[1]);
			for(int i=2;i<=ans[0];i++)
			{
				if(ans[i-1]!=ans[i])//如果两个数相同,那么他们排序后肯定是相邻的
				{
					printf(" %ld",ans[i]);
				}
			}
		    printf("\n");
		}
		
		
	}
	
	return 0;
 } 
发布了13 篇原创文章 · 获赞 2 · 访问量 340

猜你喜欢

转载自blog.csdn.net/weixin_45718149/article/details/104611576