題目連接:https://vjudge.net/problem/HDU-5389
利用數根的特性,數值在1~9的小範圍,結果在1~9的小範圍,數之間順序無關,組合數公式等進行計數DP。
關於數根的特性:
http://blog.csdn.net/ray0354315/article/details/53991199
代碼
#include<stdio.h>
#include<string.h>
#include<utility>
using namespace std;
const int mod = 258280327;
const int maxn = 100010;
typedef pair<int,int> pii;
int n,A,B;
int cnt[12];
int dp[12][12][12];
int inv[maxn];
int tp;
void read()
{
tp=0;
scanf("%d %d %d",&n,&A,&B);
memset(cnt,0,sizeof(cnt));
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
tp=(tp+x)%9;
++cnt[x];
}
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
}
void solve()
{
read();
for(int cur=1;cur<=9;cur++)
{
int C = 1;
for(int k=0;k<=cnt[cur];k++)
{
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
dp[cur][(i+1ll*k*cur)%9][(j+1ll*(cnt[cur]-k)*cur)%9]=(dp[cur][(i+1ll*k*cur)%9][(j+1ll*(cnt[cur]-k)*cur)%9]+1ll*dp[cur-1][i][j]*C%mod)%mod;
C=1ll*C*(cnt[cur]-k)%mod*inv[k+1]%mod;
}
}
int ans=dp[9][A%9][B%9];
pii p = make_pair(A%9,B%9);
if(A%9==tp&&p!=make_pair(tp,0))
ans=(ans+1)%mod;
if(B%9==tp&&p!=make_pair(0,tp))
ans=(ans+1)%mod;
printf("%d\n",ans);
}
int mp(int x,int n)
{
int ret=1;
while(n)
{
if(n&1) ret=1ll*ret*x%mod;
x=1ll*x*x%mod;
n>>=1;
}
return ret;
}
void init()
{
for(int i=1;i<maxn;i++) inv[i]=mp(i,mod-2);
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}