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