首页 > ACM题库 > HDU-杭电 > HDU 3022-Sum of Digits-动态规划-[解题报告]HOJ
2014
02-27

HDU 3022-Sum of Digits-动态规划-[解题报告]HOJ

Sum of Digits

问题描述 :

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?

输入:

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.

输出:

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.

样例输入:

4
9 81
12 9
6 10
7 9

样例输出:

9
No solution
1122
111112

http://acm.hdu.edu.cn/showproblem.php?pid=3022

http://acm.timus.ru/problem.aspx?space=1&num=1658

给你 n 和 m 问能不能找到一个一百位以内的数

使得每位的和为 n  每位平方的和为 m

又是看了别人的思路呀 伤不起呀 自己的能力还是不够呀

digits[i][j] 表示 n 为i m为j 时最少位数

num[i][j] 表示最少位数时 最靠前一位是几

让后以位数最小优先 在以考前位越小越好优先 dp

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<stack>
#include<algorithm>
#define LL long long

using namespace std;

const int N=901;
const int M=8101;
int digits[N][M];
int num[N][M];

int dp(int a,int b)
{
    if(digits[a][b]!=-1)
    return digits[a][b];
    if(a==0||b==0)
    {
        if(a==0&&b==0)
        digits[a][b]=0;
        else
        digits[a][b]=101;
        return digits[a][b];
    }
    if(a>b)
    {
        digits[a][b]=101;
        return digits[a][b];
    }
    digits[a][b]=101;
    int k;
    for(int i=1;i<=9;++i)
    {
        if(a-i>=0&&b-i*i>=0)
        {
            k=dp(a-i,b-i*i);
            if(k+1<digits[a][b])
            {
                num[a][b]=i;
                digits[a][b]=k+1;
            }
        }
    }
    return digits[a][b];
}
void print(int i,int a,int b)
{
    printf("%d",num[a][b]);
    if(i>1)
    print(i-1,a-num[a][b],b-num[a][b]*num[a][b]);
}
int main()
{
    memset(digits,-1,sizeof(digits));
    memset(num,-1,sizeof(num));
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        int k=101;
        if(n<=m&&n<N&&m<M)
        k=dp(n,m);
        if(k==101)
        printf("No solution");
        else
        {
            print(k,n,m);
        }
        printf("\n");
    }
    return 0;
}

  

 

参考:http://www.cnblogs.com/liulangye/archive/2012/07/24/2605957.html


  1. 约瑟夫也用说这么长……很成熟的一个问题了,分治的方法解起来o(n)就可以了,有兴趣可以看看具体数学的第一章,关于约瑟夫问题推导出了一系列的结论,很漂亮