题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5389
想到了门与和的关系,但是卡在了分配……上……
天哪,居然没想到这是01背包也是醉了,一直卡在怎么分配那里我去去,一看题解是背包我还以为是多重的,结果01就可以啊……
看了题解才发现,并没有啥发现了呵呵……最近有好几种题都是DP可是思路都偏了没有想到,真是奇了怪了,也不奇怪,可能就是没有很好的理解……
题解还证明了个什么什么东西,但是这题没用这个貌似也能过,用了应该更快。是这样子的:
一个数的数字根只和它mod 9之后的值有关,只要类似背包就能完成人员分配的计算。
具体证明:数字根=∑i=0wai,数字=∑i=0w10i∗ai
数字-数字根=∑i=0w(10i−1)∗ai,这个数字在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
*/