题目连接:传送门
题意:
讲一个长度为n的序列分为两组,使得一组的和为A,一组的和为B.
注意这里的和定义为这些数的和的数根。
一个数的数根的计算公式为,root = (x-1)%9+1;
很明显一个正整数的数根是1~9的分析,如果这n个数的数根分成两组使得
一组的数根为A,一组的数根为B那么这两组的数的和的数根等于(A+B)的
数根。因此我们只需要考虑组成其中一个数的情况,然后再最后进行一个
判断即可我们设dp[i][j]表示前i个数组成的数根为j的数目。
注意其中任意一组可以为空。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = 258280327;
const int maxn = 1e5+10;
LL dp[2][10];
int a[maxn];
int main()
{
int t,A,B,n;
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=(sum+a[i]-1)%9+1;
}
int cur=0;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++){
cur^=1;
memset(dp[cur],0,sizeof(dp[cur]));
for(int j=0;j<10;j++){
dp[cur][j]=(dp[cur][j]+dp[cur^1][j])%mod;
int t = (j+a[i]-1)%9+1;
dp[cur][t]=(dp[cur][t]+dp[cur^1][j])%mod;
}
}
int tot = (A+B-1)%9+1;
LL ans = 0;
if(tot == sum){
ans=dp[cur][A];
if(A==sum) ans--;
}
if(A==sum) ans++;
if(B==sum) ans++;
printf("%I64d\n",ans);
}
return 0;
}