URAL 1658
来源:互联网 发布:寿命试验 二型删失数据 编辑:程序博客网 时间:2024/04/26 12:30
题目大意:求出T个最小的满足各个位的和为S1,平方和为S2的数。按顺序输出。数的位数大于100或者不存在这样一个数时,输出:No solution。
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
数据规模:T<=10000,1<=S1,S2<=10000。
理论基础:无。
题目分析:用dp[i][j]表示各个位的和为i,平方和为j的最小的数的位数。print[i][j]存储dp[i][j]时最高位选择的数字,用于最后输出答案。
可以肯定的是:S1与S2必然同奇偶。而且:S1<=900,S<=8100,否则无解。
证明同奇偶:观察S1^2的展开式中除了平方项,其余项的系数均为2为偶数(将S1,表示为各个位和的形式展开),所以其余项的和偶数。而剩下的项的和即为S2,所以:S2与S1^2同奇偶。又因为S1与S1^2同奇偶,所以S1与S2同奇偶得证。
所以dp转移方程为:min(dp[i][j],dp[i-k][j-k*k](k<=i,k*k<=j))。
同时,因为使用的判断条件为dp[i][j]<dp[i-k][j-k*k]且k是以升序枚举,所以得出的解保证了最小性。
代码如下:
#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>#include<queue>#include<ctime>#include<vector>using namespace std;typedef double db;#define DBG 0#define maa (1<<31)#define mii ((1<<31)-1)#define ast(b) if(DBG && !(b)) { printf("%d!!|\n", __LINE__); while(1) getchar(); } //调试#define dout DBG && cout << __LINE__ << ">>| "#define pr(x) #x"=" << (x) << " | "#define mk(x) DBG && cout << __LINE__ << "**| "#x << endl#define pra(arr, a, b) if(DBG) {\ dout<<#arr"[] |" <<endl; \ for(int i=a,i_b=b;i<=i_b;i++) cout<<"["<<i<<"]="<<arr[i]<<" |"<<((i-(a)+1)%8?" ":"\n"); \ if((b-a+1)%8) puts("");\}template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }template<class T> inline bool updateMax(T& a, T b) { return a<b? a=b, true: false; }typedef long long LL;typedef long unsigned int LU;typedef long long unsigned int LLU;#define M 910#define N 8110int m,n,T;char dp[M][N],print[M][N];void init(){ for(int i=0;i<=900;i++) { for(int j=0;j<=8100;j++)dp[i][j]=101; } dp[0][0]=0; for(int i=1;i<=900;i++) { for(int j=i;j<=8100&&j<=i*i;j++) { for(int k=1;k<=9&&k<=i&&k*k<=j;k++) { if(i-k>j-k*k)break; if(dp[i][j]>dp[i-k][j-k*k]+1) { print[i][j]=k; dp[i][j]=dp[i-k][j-k*k]+1; } } } }}int main(){ init(); scanf("%d",&T); while(T--) { scanf("%d%d",&m,&n); if(m>n||m>900||n>8100||(m^n)&1||dp[m][n]>100) { printf("No solution\n"); continue; } while(m&&n) { int t=print[m][n]; printf("%d",t); m-=t; n-=t*t; } puts(""); }return 0;}其中,因为有多个测例,所以选择预处理出答案,效率可能会更高一些。
by:Jsun_moon http://blog.csdn.net/jsun_moon
- URAL 1658
- URAL
- 【ural】
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- URAL
- hdu3501 Calculation 2 欧拉函数
- HOG中的三线性插值
- 56页E4
- HDU 2136 Largest prime factor
- jdk 动态代理
- URAL 1658
- hdu1176免费馅饼 dp
- SVN 如何提交 SO 库文件
- Android 设置半透明画笔
- Android 字符串、byte数组与16进制数组间的转换
- C++学习vector与数组优缺点
- Nginx-ngx_palloc
- UITOOLBAR的应用
- 在A20上演示老罗的Android硬件抽象层(HAL)概要介绍和学习计划1