题目连接:传送门
题意:
讲一个长度为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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-04 17:25:50