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);
    }
}

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