HDU_5456_数位dp

http://acm.hdu.edu.cn/showproblem.php?pid=5456

转化成a=b+c,dp[i][a][b][c]表示剩余i木棒,a是否有进位,b是否首尾,c是否首位,注意每次都要memset。

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;

int n,m,stick[10] = {6,2,5,5,4,5,6,3,7,6};
LL dp[505][2][2][2];

LL dfs(int sum,int a,int b,int c)
{

    if(sum < 0) return 0;
    if(dp[sum][a][b][c] != -1)  return dp[sum][a][b][c];
    if(b && c)
    {
        if(!a && sum == 0)  return 1;
        if(a && sum == stick[1])    return 1;
    }
    if(sum == 0)    return 0;
    LL& temp = dp[sum][a][b][c];
    temp = 0;
    if(b == 0 && c == 0)
    {
        for(int i = 0;i <= 9;i++)
        {
            for(int j = 0;j <= 9;j++)
            {
                int sub = stick[i]+stick[j]+stick[(i+j+a)%10];
                temp += dfs(sum-sub,(i+j+a)/10,0,0);
                if(i != 0)  temp += dfs(sum-sub,(i+j+a)/10,1,0);
                if(j != 0)  temp += dfs(sum-sub,(i+j+a)/10,0,1);
                if(i != 0 && j != 0)    temp += dfs(sum-sub,(i+j+a)/10,1,1);
                temp %= m;
            }
        }
    }
    else if(b == 0)
    {
        for(int i = 0;i <= 9;i++)
        {
            int sub = stick[i]+stick[(i+a)%10];
            temp += dfs(sum-sub,(i+a)/10,0,1);
            if(i != 0)  temp += dfs(sum-sub,(i+a)/10,1,1);
            temp %= m;
        }
    }
    else if(c == 0)
    {
        for(int i = 0;i <= 9;i++)
        {
            int sub = stick[i]+stick[(i+a)%10];
            temp += dfs(sum-sub,(i+a)/10,1,0);
            if(i != 0)  temp += dfs(sum-sub,(i+a)/10,1,1);
            temp %= m;
        }
    }
    temp %= m;
    return temp;
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int i = 1;i <= T;i++)
    {
        memset(dp,-1,sizeof(dp));
        scanf("%d%d",&n,&m);
        printf("Case #%d: %lld
",i,dfs(n-3,0,0,0));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhurb/p/5910966.html