• 51nod1043(数位dp)


    题目链接: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 }
  • 相关阅读:
    P2986 [USACO10MAR] Great Cow Gathering G
    L3025 那就别担心了 (天梯赛)
    P7960 [NOIP2021] 报数
    #10121. 「一本通 4.2 例 3」与众不同
    2016第七届蓝桥杯大赛个人赛省赛(软件类)真题 C大学A组
    L33 胜利者集合(天梯赛)
    士兵过河
    P1899 魔法物品
    状压dp专题
    P3177 [HAOI2015] 树上染色
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6329594.html
Copyright © 2020-2023  润新知