codeforces 856c Eleventh Birthday

C. Eleventh Birthday
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

It is Borya's eleventh birthday, and he has got a great present: n cards with numbers. The i-th card has the number ai written on it. Borya wants to put his cards in a row to get one greater number. For example, if Borya has cards with numbers 131, and 12, and he puts them in a row in this order, he would get a number 13112.

He is only 11, but he already knows that there are n! ways to put his cards in a row. But today is a special day, so he is only interested in such ways that the resulting big number is divisible by eleven. So, the way from the previous paragraph is good, because 13112 = 1192 × 11, but if he puts the cards in the following order: 31112, he would get a number 31112, it is not divisible by 11, so this way is not good for Borya. Help Borya to find out how many good ways to put the cards are there.

Borya considers all cards different, even if some of them contain the same number. For example, if Borya has two cards with 1 on it, there are two good ways.

Help Borya, find the number of good ways to put the cards. This number can be large, so output it modulo 998244353.

Input

Input data contains multiple test cases. The first line of the input data contains an integer t — the number of test cases (1 ≤ t ≤ 100). The descriptions of test cases follow.

Each test is described by two lines.

The first line contains an integer n (1 ≤ n ≤ 2000) — the number of cards in Borya's present.

The second line contains n integers ai (1 ≤ ai ≤ 109) — numbers written on the cards.

It is guaranteed that the total number of cards in all tests of one input data doesn't exceed 2000.

Output

For each test case output one line: the number of ways to put the cards to the table so that the resulting big number was divisible by 11, print the number modulo 998244353.

Example
input
Copy
4
2
1 1
3
1 31 12
3
12345 67 84
9
1 2 3 4 5 6 7 8 9
output
2
2
2
31680

题意:给你一些数字,必须全用完拼成一个排列,一共n!种,问是11倍数的有多少种。

两个数字相同如果位置不同也是不同的方案。

小学数学:11的倍数abs(Σ(奇数位)-Σ(偶数位))是11的倍数。

所以我们在拼数字的时候对于模数的贡献也就出来了。

但是我们注意到,如果当前的排列新增一个数字,如果原来的数字长度为奇数,那么新加入的数字奇偶就反转了,所以这个数字拼接奇数位贡献为负。

所以长度为偶数的数字不会影响奇数,奇数影响偶数的情况也只有n/2种。

我们把奇偶数分开dp,之后根据奇数对偶数的影响进行合并即可。

dp[i][j][k]表示前i个奇数,有j个从偶数位开始,模数为k的方案数。

dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i1][j][ka[i]]+dp[i1][j1][k+a[i]]dp[i][j][k]=dp[i-1][j][k-a[i]]+dp[i-1][j-1][k+a[i]],a[i]表示贡献。

偶数同理。

之后用阶乘和组合数合并奇偶即可,组合数在线计算。

我们可以随意打乱排列顺序,并且选择的数字也是随意的,对应合并时乘的数字。

代码:

#include <bits/stdc++.h>
#define ll long long
#define rsw 998244353
#define add(x,y) (x=((x)+(y)>=rsw)?((x)+(y)-rsw):((x)+(y)))
using namespace std;
int T,ans,n,a[2005],b[2005],c[2005],dp1[2005][2005][11],dp2[2005][2005][11],n1,n2,len,now,p[2005],inv[2005];
int C(int n,int m){return (ll)p[n]*inv[m]%rsw*inv[n-m]%rsw;}
int get(int m,int n){return !m?(n?0:1):(ll)p[n]*C(n+m-1,n)%rsw;}
int main()
{
    scanf("%d",&T);
    p[0]=inv[0]=inv[1]=1;
    for(int i=1;i<2005;i++) p[i]=(ll)p[i-1]*i%rsw;
    for(int i=2;i<2005;i++) inv[i]=(ll)(rsw-rsw/i)*inv[rsw%i]%rsw;
    for(int i=2;i<2005;i++) inv[i]=(ll)inv[i]*inv[i-1]%rsw;
    while(T--)
    {
        scanf("%d",&n),n1=n2=ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            for(len=0,now=a[i];now;now/=10) len++;
            if(len&1) b[++n1]=a[i]%11;
            else c[++n2]=a[i]%11;
        }
        memset(dp1[0],0,sizeof dp1[0]);memset(dp2[0],0,sizeof dp2[0]);
        dp1[0][0][0]=dp2[0][0][0]=1;
        for(int i=1;i<=n1;i++)
            for(int j=0;j<=i;j++)
                for(int k=0;k<11;k++)
                {
                    dp1[i][j][k]=0;
                    add(dp1[i][j][k],dp1[i-1][j][(k-b[i]+11)%11]);
                    if(j) add(dp1[i][j][k],dp1[i-1][j-1][(k+b[i])%11]);
                }
        for(int i=1;i<=n2;i++)
            for(int j=0;j<=i;j++)
                for(int k=0;k<11;k++)
                {
                    dp2[i][j][k]=0;
                    add(dp2[i][j][k],dp2[i-1][j][(k-c[i]+11)%11]);
                    if(j) add(dp2[i][j][k],dp2[i-1][j-1][(k+c[i])%11]);
                }
        for(int i=0;i<=n2;i++)
            for(int k=0;k<11;k++)
                add(ans,(ll)dp1[n1][n1/2][k]*p[n1/2]%rsw*p[n1-n1/2]%rsw*dp2[n2][i][(11-k)%11]%rsw*get(n1+1-(n1+1)/2,n2-i)%rsw*get((n1+1)/2,i)%rsw);
        printf("%d\n",ans);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章