标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5389
想到了门与和的关系,但是卡在了分配……上……
天哪,居然没想到这是01背包也是醉了,一直卡在怎么分配那里我去去,一看题解是背包我还以为是多重的,结果01就可以啊……
看了题解才发现,并没有啥发现了呵呵……最近有好几种题都是DP可是思路都偏了没有想到,真是奇了怪了,也不奇怪,可能就是没有很好的理解……
题解还证明了个什么什么东西,但是这题没用这个貌似也能过,用了应该更快。是这样子的:
一个数的数字根只和它mod 9之后的值有关,只要类似背包就能完成人员分配的计算。
具体证明:数字根=∑?i=0?w??a?i??,数字=∑?i=0?w??10?i???a?i??
数字-数字根=∑?i=0?w??(10?i???1)?a?i??,这个数字在mod 9域下为0
(PS:有些题目给出的范围条件特别重要,很有可能是dp的关键点,要特别注意)
#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <string> #include <cstdlib> #include <vector> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int mod=258280327; const int maxd=1e5+5; int n,A,B; int dp[maxd][20],a[maxd]; int root(int x) { int ans=0; while(x>0) { ans+=x%10; x/=10; } if(ans>9) return root(ans); else return ans; } int main() { int kase; scanf("%d",&kase); while(kase--) { scanf("%d",&n); scanf("%d%d",&A,&B); int sum=0; for(int i=1; i<=n; i++) scanf("%d",&a[i]),sum+=a[i]; mem(dp,0); dp[0][0]=1; for(int i=1; i<=n; i++) { for(int j=0; j<=9; j++) { (dp[i][j]+=dp[i-1][j])%=mod; (dp[i][root(j+a[i])]+=dp[i-1][j])%=mod; } } int id=root(sum),ans=0; if(id==root(A+B)) { ans+=dp[n][A]; if(id==A) ans--; } if(id==A) ans++; if(id==B) ans++; cout<<ans<<endl; } return 0; } /* 4 3 9 1 1 2 6 3 9 1 2 3 3 5 2 3 1 1 1 1 1 9 9 9 1 2 3 4 5 6 7 8 9 */
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/whoisvip/article/details/47620437