2015多校第8场 HDU 5389 Zero Escape DP,递推

来源:互联网 发布:mysql排序规则 编辑:程序博客网 时间:2024/06/04 18:49

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5389

题意:给出n个数和两个值A,B,要求将n个数分成两部分,使得每部分数和的数根的值等于A和B,求种数

解法:DP。   dp[i][j]表示取前i个数字中的若干个,按给定规则,算出来的和为j的方案数,dp[i][j]=dp[i-1][j]+dp[i-1][tmp](tmp为j-arr[i],若小于等于0,需加9调整),转移注意一个特殊的地方,就是当前位可以取并且前面都不取的情况,还有就是当a+b==a的时候,如果直接输出dp[n][a]不对,因为遗漏了a中都不取都放到b里面,而b恰好和sum相同的情况,这里的sum就是总和的数根。当总和和a+b不等时需要特殊处理。


#include <bits/stdc++.h>using namespace std;const int mod = 258280327;const int maxn = 1e5+10;int t, n, a, b, dp[maxn][11];int val[maxn];int cal(int x){    int ret = 0;    while(x){        ret += x%10;        x /= 10;    }    if(ret > 9) return cal(ret);    else return ret;}int main(){    scanf("%d", &t);    while(t--)    {        int sum = 0;        scanf("%d %d %d", &n,&a,&b);        memset(dp, 0, sizeof(dp));        for(int i=1; i<=n; i++) scanf("%d", &val[i]), sum+=val[i];        sum = cal(sum);        int xx = cal(a+b);        if(sum == xx){            dp[1][val[1]] = 1;            dp[1][0] = 1;            for(int i=2; i<=n; i++){                dp[i][0] = 1;                for(int j=1; j<10; j++){                    int tmp = j-val[i];                    if(tmp < 0){                        tmp += 9;                        dp[i][j] = (dp[i-1][tmp] + dp[i-1][j])%mod;                    }                    else if(tmp == 0){                        dp[i][j] = (dp[i-1][j] + dp[i-1][9] + dp[i-1][0])%mod;                    }                    else{                        dp[i][j] = (dp[i-1][j] + dp[i-1][tmp])%mod;                    }                }            }            if(b == sum){                printf("%d\n", (dp[n][a]+1)%mod);            }            else{                printf("%d\n", dp[n][a]);            }        }        else{            int ans = 0;            if(a==sum){                ans++;            }            if(b==sum){                ans++;            }            printf("%d\n", ans);        }    }    return 0;}

原创粉丝点击