• URAL 1658


    题目大意:求出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!!|
    ", __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?" ":"
    "); 
        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 8110
    int 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
    ");
                continue;
            }
            while(m&&n)
            {
                int t=print[m][n];
                printf("%d",t);
                m-=t;
                n-=t*t;
            }
            puts("");
        }
    	return 0;
    }
        其中,因为有多个测例,所以选择预处理出答案,效率可能会更高一些。




  • 相关阅读:
    利用flashBack恢复误删除(delete)的表数据
    [原创] [YCM] YouCompleteMe安装完全指南
    关于dll的一点收获
    could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'
    化不利为有利
    突破软件试用期的"土方法"
    网络求职的成功率一般2个月是发1000份简历,有8份面试,2份成功,一个是你不想去的,另一个可能是你相对满意的。
    一个简易的dota改键助手
    linux 版本控制服务-git
    django modelform模块
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3279831.html
Copyright © 2020-2023  润新知