您的位置:首页 > 其它

Milliard Vasya's Function(Ural_1353)

2016-06-03 10:40 337 查看
Vasya is the beginning mathematician. He decided to make an important contribution to the science and to become famous all over the world. But how can he do that if the most interesting facts such as Pythagor’s theorem are already proved? Correct! He is to think out something his own, original. So he thought out the Theory of Vasya’s Functions. Vasya’s Functions (VF) are rather simple: the value of the Nth VF in the point S is an amount of integers from 1 to N that have the sum of digits S. You seem to be great programmers, so Vasya gave you a task to find the milliard VF value (i.e. the VF with N = 109) because Vasya himself won’t cope with the task. Can you solve the problem?

Input

Integer S (1 ≤ S ≤ 81).

Output

The milliard VF value in the point S.

Sample

input

1

output

10

代码

一开始打表找规律,虽然能看出点什么来但还是差那么一点,直接用动规的思想来想(谢QAQ巨巨的指导), 假设我们当前要求的是100以内各位数之和和等于s的数有多少个,可以想到就是10以内各位数之和等于s的数的个数再加上10到100内的各位数之和等于s的个数。令dp[i][j]就代表10的j次方内各位数之和等于i的数的个数,那么dp[i][j] = dp[i][j - 1] + (10的j-1次方到10的j次方内各位数之和等于i的数的个数)。那么后边这一部分怎么求呢?我们可以把j位数拆成j-1位数再加一位,要想让各位数之和等于i,那么加的这一位数只能是1到9中的任意一个数(不能是0的原因不用说了吧),假设我们加的数是1,那么我们剩下j-1位的和只能是i-1,也就是dp[i - 1][j - 1],如果加的数是2,那么我们剩下的j-1位的和就是dp[i - 2][j - 1],以此类推,状态转移方程就出来了,dp[i][j] = dp[i][j - 1] + dp[i - k][j - 1] ( 1 <= k <= 9)

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int main()
{
long long dp[83][12];
memset(dp, 0, sizeof(dp));
for(int i = 0; i <= 9; i++)
{
dp[i][1] = 1;
dp[0][i] = 1; //这个初始化是因为s小于10的时候比如说s=2时,会有2000这样的数,这在我们分的情况中没有出现,
} //因此可以把这个用不到的s=0时的处值设成1,s从1到9都可以加到这个数,方便计算
for(int j = 2; j <= 9; j++)
{
for(int i = 1; i <= 81; i++)
{
dp[i][j] = dp[i][j - 1];
for(int k = 1; k <= 9 && k <= i; k++)
{
dp[i][j] += dp[i - k][j - 1];
}
}
}
dp[1][9]++; //1还多一种1000000000的情况
int n;
scanf("%d", &n);
printf("%lld\n", dp
[9]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: