timus 1353. Milliard Vasya's Function 解题报告 URAL
一个函数,定义为输入s,输出1-N中各个位上的数之和为s的个数,n=10^9
这个题也是划归到DP一类里面,可是我对DP的状态转移貌似还是不清楚,没理解透,所以愣是没想出来,反正一碰到这种题我就向往排列组合上面想!
后来看了别人的思路才一下子豁然开朗,位数为i位时,能组成的位数和j也要考前一个转化而来,当前最高位可以为0,1,2,3,……9那么就是dp[i-1][j-k] k是0--9,并且小于等于j
初次之外还有边界需要处理!
{///这里的初始化很关键,dp[i][j]表示最多用i位,一共能组成多少个各位上的和是j的数
dp[1][i]=1;
dp[i][0]=1;///这一句加不加将会影响后面的判断,如果不加那么dp[i-1][0]直接等于0也就少几种情况首位自己贡献0-9的十种情况
}///dp[10][1]=10;
AC代码
#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
int dp[11][90];
void init()
{
memset(dp,0,sizeof(dp));
for(int i=1; i<10; ++i)
{///这里的初始化很关键,dp[i][j]表示最多用i位,一共能组成多少个各位上的和是j的数
dp[1][i]=1;
dp[i][0]=1;///这一句加不加将会影响后面的判断,如果不加那么dp[i-1][0]直接等于0也就少几种情况首位自己贡献0-9的十种情况
}///dp[10][1]=10;
for(int i=2; i<=9; ++i)
{
for(int j=1; j<=81; j++)
{
for(int k=9; k>=0; k--)if(j>=k) dp[i][j]+=dp[i-1][j-k];
}
}
}
int s;
int main ( )
{
init();
//cout<<dp[2][1]<<endl;
while(scanf("%d",&s)!=EOF)
{
if(s==1)cout<<10<<endl;
else cout<<dp[9][s]<<endl;
}
return 0;
}
timus 1353. Milliard Vasya's Function 解题报告 URAL