51Nod1043 幸运号码(动归数位dp)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_42391248/article/details/85198805

我们用dp[i][j]表示的是前i位的数字和为j,j最大为9*i  ,前i位每位都是9的时候。   这样假如我们求得了dp[n][1]一直到dp[n][9*n]的数字,那么最终结果就是dp[n][1] * dp[n][1]  +   ... + dp[n][9*n] * dp[n][9*n]  .  但是这里还有一个问题就是,dp[i][j] 表示的是前i位的数字和为j,但是我们知道前面的那个 i位 是 不能有前置0的,所以还有处理一下。

求结果的时候就是sum(有前置0的结果)*(不含前置0的结果)。没有前置0的结果是 dp[i][j] - dp[i-1][j] ,  因为每次都是在前面加数字,所以要是i位和i-1位的和一样,就是前置0的数字了。


接下来就是怎么求解dp[i][j] 了, dp[i][j]+= dp[i-1][j-k]  ;  (j>=k,k=0,1,2...9)  .很好理解 。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int Mod=1e9+7;
long long dp[1005][9045];//前i个数的和为j 
int main()
{
	int i,j,k;
	memset(dp,0,sizeof(dp));
	for(i=0;i<=9;i++) 
		dp[1][i]=1;
	for(i=2;i<=1000;i++)
		for(j=0;j<=i*9;j++)
			for(k=0;k<=9;k++)
				if(j>=k)
					dp[i][j]=(dp[i][j]+dp[i-1][j-k])%Mod;
	int n;
	long long sum=0;
	cin>>n;
	for(i=1;i<=9*n;i++)
		sum=(sum+(dp[n][i]-dp[n-1][i])*dp[n][i])%Mod;		
	cout<<sum<<endl;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_42391248/article/details/85198805
今日推荐