51Nod1043 幸運號碼(動歸數位dp)
阿新 • • 發佈:2018-12-23
我們用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; }