题意:
有n个人,每个人有一个value值,有两扇门A,B分别各有一个value,现在要讲n个人分为两组分别从两个门进入,要求是每组人的value值的和(迭代的求,直至变为一位数字)等于该门的value值,问一共有多少种进入的方法。
分析:
首先我们可以发现,假如能够进去的话,那么所有的人的value值的和刚好等于两扇门的value值的和。或者只进入一个门,也就是只等于一个门的value值。计算这个和的方法就是先真的求出和然后模上9就可以了的。
然后我们可以考虑用dp的方式解决问题了。
dp[i][j]表示的是前i个人中选出一部分人的value值之和等于j的种数。
然后我们可以想到状态转移方程:dp[i][j] = (dp[i-1][j]+dp[i-1][(j+9-a[i])%9]);
最后我们在n个人中选出一部分人的value值之和等于A门的alue,那剩下的value和就等于B门的value了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define mod 258280327
int const maxn = 100005;
int dp[maxn][10];
//dp[i][j]表示的是前i个人中的取得的价值为j的方案数
//由于处理的是直接%9,所以价值为9变化为价值为0
int a[maxn];
int main()
{
int t,n,A,B;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&A,&B);
int sum = 0 ;
for(int i = 1 ; i <= n ; i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sum%=9;
int ans = 0 ;
if(sum==(A+B)%9)
{
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]+dp[i-1][(j+9-a[i])%9])%mod;
}
}
if(sum==(B%9))ans++;
printf("%d\n",(dp[n][A]+ans)%mod);
}
else
{
if(sum==(A%9))ans++;
if(sum==(B%9))ans++;
printf("%d\n",ans);
}
}
return 0;
}