hello kity
期待您的批阅,由于写解题报告时 不一定考虑的很周到,所以如果您有什么不懂的地方,请您留言,然而一天之内我肯定会看见您信息,再对代码注释详细,让您更好的阅读
分类
最新评论
最新留言
链接
RSS
计数器
223103
功能
HDU 1271(整数对 经典!)
spoiler
posted @ 2011年4月17日 19:31
in 未分类
, 4243 阅读
题目大意:
Problem Description
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)所以小希可以因此而得到一个额外的糖果。
所以现在小希希望你编写一个程序,来帮助她找到尽可能多的解。
例如,Gardon想的是A=31,B=3 告诉小希N=34,
小希除了回答31以外还可以回答27(27+7=34)所以小希可以因此而得到一个额外的糖果。
Input
输入包含多组数据,每组数据一行,包含一个数N(1<=N<=10^9),文件以0结尾。
Output
对于每个输入的N,输出所有符合要求的解(按照大小顺序排列)如果没有这样的解,输出"No solution."
题目分析:第一次,我的思路是从一半开始枚举,发现这样超时了
TLE代码:
#include<iostream> #include<stdio.h> #include<math.h> using namespace std; int s[1000]; inline int solve(int x){ int k,ans,i,j; int c,sum,t,times=1; while(c){ c/=10; k++; } int xx=pow(10,k-2); for(i=xx;i<=x;i++){ k=0; c=i; while(c){ c/=10; k++; } for(j=1;j<=k;j++){ c=i; sum=0; int w=(int)pow(10,k-j); if(j==1){ sum=c%w; } if(j==k){ sum=c/10; } if(j!=k&&j!=1){ t=c%w; int p=c/w; p/=10; p=p*((int)pow(10,k-j)); sum=p+t; } if(sum+i==x){ s[times++]=i; } } } return times-1; } int main(){ int x,t,i; while(scanf("%d",&x),x){ t=solve(x); if(t==0) printf("No solution.\n"); else{ for(i=1;i<=t;i++) printf("%d ",s[i]); printf("\n"); } } return 0; }
后来看了一下解题报告,后来终于理解了,现在让我来说说这题的做法跟规律吧{^_^}
首先假设X的第k位拿走,然后加上加上X的和正好等于N!
这样的话 我们可以把X 分解成:X= a+b * 10^k +c * 10^( k+1 ); 这里特别强调一下, a代表的是比第k位后面的低位数子,可能是多位,b仅仅代表一个数值,即你选择拿开的那位数,c代表的是比k位高的高位数字,例如:12345 您想拿走3的话 这时候a=45,c=12,b=3; 然后拿走之后就会组合成另一个数:Y=a + c * 10^k; 然后X+Y=2 * a + b * 10 ^k +11 * c * 10^k;
现在如果N=X+Y;他必定满足上面那种结构!所以我们考虑这种结构特征就可以了,首先上述表达式的低位是2*a 可能发生进位!
所以b的值可能是10,但是 都不影响c的值, 这个时候只需要分两种不同的b的情况,来求出a,然后验证一下 是不是等于N就可以了!
AC代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<set> using namespace std; void solve(int x,set<int> &result){ int k,high,b2,a; int c,sum,b1; for(k=1;k<=x;k*=10){ high=x/k; c=high/11; c*=k; b1=high%11; if((b1!=0||c!=0)&&b1<10){ b1*=k; a=(x-b1-11*c)/2; if(2*a+b1+11*c==x) result.insert(a+b1+c*10); } b2=high%11-1; if((b2!=0||c!=0)&&b2>=0){ b2*=k; int a2=(x-b2-11*c)/2; if(x==2*a2+b2+11*c) result.insert(a2+b2+10*c); } } } int main(){ int x,i; while(cin>>x,x){ set<int>result; //set结构不仅可以排序,而且可以去除重复的 //下次要多多学习,总结! solve(x,result); if(result.empty()){ printf("No solution.\n"); } else{ set<int>::iterator it=result.begin(); printf("%d",*it); while(++it!=result.end()) printf(" %d",*it); printf("\n"); } } return 0; }
还有一种代码思路一样
AC代码
#include<iostream> #include<stdio.h> #include<algorithm> using namespace std; int s[1000],times; int cmp(int x,int y){ return x<y; } int solve(int x){ int k,high,b2,a; int c,sum,b1; times=0; for(k=1;k<=x;k*=10){ high=x/k; c=high/11; c*=k; b1=high%11; if((b1!=0||c!=0)&&b1<10){ b1*=k; a=(x-b1-11*c)/2; if(2*a+b1+11*c==x) s[++times]=a+b1+c*10; } b2=high%11-1; if((b2!=0||c!=0)&&b2>=0){ b2*=k; a=(x-b2-11*c)/2; if(x==2*a+b2+11*c) s[++times]=a+b2+10*c; } } return 0; } int main(){ int x,t,i; while(scanf("%d",&x)&&x){ solve(x); if(times==0){ printf("No solution.\n"); } else{ sort(s+1,s+1+times,cmp); printf("%d",s[1]); for(i=2;i<=times;i++){ if(s[i]!=s[i-1]) printf(" %d",s[i]); } printf("\n"); } } return 0; }
题目总结:今后一定要大量深入学校STL函数!还有这题的去除重复不能忘记,同时要深刻认识本题的思路,太巧妙,强大了