题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043
题意:中文题诶~
思路:数位dp
我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的;
我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,交换顺序的两种情况都是所有情况里面的情况),加k=0就相当于加了一个前导0,那么我们不难想到动态转移方程式为:
dp[i][j]=∑dp[i-1][j-k] (0<=k<=9)
去前导0为dp[i][j]-dp[i-1][j];
那么对于长度为2*i和为j的组合情况为:dp[i][j]*(dp[i-1][j]) (前部分要考虑前导0,后部分不用考虑);
对于我们要求的答案,直接累加就好了啦.
代码:
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 const int mod=1e9+7; 6 const int MAXN=1010; 7 ll dp[MAXN][MAXN*9]; //***dp[i][j]从存储长度为2*i一半和为j的情况数 8 9 int main(void){ 10 ll ans=0; 11 int n; 12 cin >> n; 13 dp[0][0]=1; //***一开始计算时要把所有前导0都算进去 14 for(int i=1; i<=n; i++){ 15 for(int j=0; j<=i*9; j++){ 16 for(int k=0; k<=9; k++){ 17 if(j>=k){ 18 dp[i][j]=(dp[i][j]+dp[i-1][j-k])%mod; 19 }else{ 20 break; 21 } 22 } 23 } 24 } 25 for(int i=0; i<=9*n; i++){ 26 ans=(ans+(dp[n][i]-dp[n-1][i])*dp[n][i])%mod; 27 } 28 cout << ans << endl; 29 return 0; 30 }
时间: 2024-12-26 15:28:17