HDU3022:Sum of Digits

来源:互联网 发布:移民英国 知乎 编辑:程序博客网 时间:2024/04/29 09:50

Sum of Digits

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 149    Accepted Submission(s): 46


Problem Description
Petka thought of a positive integer n and reported to Chapayev the sum of its digits and the sum of its squared digits. Chapayev scratched his head and said: "Well, Petka, I won't find just your number, but I can find the smallest fitting number." Can you do the same?
 

Input
The first line contains the number of test cases t (no more than 10000). In each of the following t lines there are numbers s1 and s2 (1 ≤ s1, s2 ≤ 10000) separated by a space. They are the sum of digits and the sum of squared digits of the number n.
 

Output
For each test case, output in a separate line the smallest fitting number n, or "No solution" if there is no such number or if it contains more than 100 digits.
 

Sample Input
49 8112 96 107 9
 

Sample Output
9No solution1122111112
 

Source
2009 Multi-University Training Contest 6 - Host by WHU
 

Recommend
gaojie
 

根据output的提示,结果不可能大于100位,我们可以猜出,s1最大就是900,s2最大是8100,所以,完全可以(s1 * s2)的复杂度。
dp[i][j] = min(dp[i - k][j - k * k] + 1, dp[i][j]),其中i表示和,j表示平方和是,k表示多出最高位是k,dp数组记录位数,同时开一个d数组记录可行方案的首位。

根据贪心思想,让结果最小,所以先尽量求出最小的位数,之后根据位数构造最小的数。得出最小位数后,可以递归求出答案(d数组记录的是可行方案的首位,所以递归很好实现。)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

int dp[901][8101], d[901][8101];
int T, n, m;

int main()
{
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= 9; ++i)
    {
        dp[i][i * i] = 1;
        d[i][i * i] = i;
    }
    for (int i = 1; i <= 900; ++i)
    {
        for (int j = i; j <= 8100; ++j)
        {
            for (int k = 1; k <= 9; ++k)
            {
                if (i < k || j < k * k) break;
                if (dp[i - k][j - k * k] == 0 || dp[i - k][j - k * k] == 100) continue;
                if (dp[i][j] == 0 || dp[i - k][j - k * k] + 1 < dp[i][j])
                {
                    dp[i][j] = dp[i - k][j - k * k] + 1;
                    d[i][j] = k;
                }
            }
        }
    }
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        if (n > 900 || m > 8100 || dp[n][m] == 0)
        {
            printf("No solution\n");
            continue;
        }
        while (dp[n][m])
        {
            int dig = d[n][m];
            printf("%d", dig);
            n -= dig;
            m -= dig * dig;
        }
        printf("\n");
    }
    return 0;
}
原创粉丝点击