1. 程式人生 > >【Atcoder - ARC102E】Stop. Otherwise...

【Atcoder - ARC102E】Stop. Otherwise...

@Stop. Otherwise…@


@題目描述 - [email protected]

Time limit : 2sec / Memory limit : 1024MB

Score : 700 points

Problem Statement


Takahashi throws N dice, each having K sides with all integers from 1 to K. The dice are NOT pairwise distinguishable. For each i=2,3,…,2K, find the following value modulo 998244353:

The number of combinations of N sides shown by the dice such that the sum of no two different sides is i.
Note that the dice are NOT distinguishable, that is, two combinations are considered different when there exists an integer k such that the number of dice showing k is different in those two.

Constraints
1≤K≤2000
2≤N≤2000
K and N are integers.

Input
Input is given from Standard Input in the following format:
K N

Output
Print 2K−1 integers. The t-th of them (1≤t≤2K−1) should be the answer for i=t+1.

Sample Input 1
3 3
Sample Output 1
7
7
4
7
7

For i=2, the combinations (1,2,2),(1,2,3),(1,3,3),(2,2,2),(2,2,3),(2,3,3),(3,3,3) satisfy the condition, so the answer is 7.
For i=3, the combinations (1,1,1),(1,1,3),(1,3,3),(2,2,2),(2,2,3),(2,3,3),(3,3,3) satisfy the condition, so the answer is 7.
For i=4, the combinations (1,1,1),(1,1,2),(2,3,3),(3,3,3) satisfy the condition, so the answer is 4.

Sample Input 2
4 5
Sample Output 2
36
36
20
20
20
36
36

Sample Input 3
6 1000
Sample Output 3
149393349
149393349
668669001
668669001
4000002
4000002
4000002
668669001
668669001
149393349
149393349

@大致題意@

有N個數。對於每一個i(2<=i<=2*K),給這N個數賦值,值為[1…K]之間的一個整數。計算任意兩個整數之和都不等於i的賦值方案數。注意N個數之間沒有順序。
1<=N,K<=2000。

@分析@

考慮沒有限制的情況,我們令Xi=有多少個數的值為i。則就是求解下面這個方程的取值方案數:

i = 1 K X i = N X i >= 0

這是一個組合數學的經典問題。我們可以令Yi=Xi+1,則方程變為:

i = 1 K Y i = N + K Y i >= 1

可以發現第一個方程的每一個解和第二個方程是一一對應的。即第一個方程解的數量等於第二個方程解的數量。
使用隔板法。有N+K個物體,N+K-1個間隔。從這N+K-1個間隔中選擇K-1個放置隔板,將這N個數分為K塊。第i塊的大小對應了Yi的取值。則方案數為 C N + K 1 K 1

我們發現限制可以分為兩類:
(1)如果p與i-p都在範圍[1…K]內,則p與i-p不能同時出現。
(2)如果p*2=i,則p只能出現0次或1次。
對於(2)這種情況,我們發現i是偶數,並且p是唯一的。則我們列舉p的出現次數,分兩類討論並把方案數相加。這樣我們就只剩下一個限制了。

假設p與i-p都在範圍[1…K]內,我們就稱(p, i-p)是一個“限制對”,否則稱p是不受限制的。我們令f(x, y, z)表示有x個限制對,y個不受限制的值,需要給z個數賦值的方案數。
怎麼求解f?我們列舉z個數裡面出現了q個受限制的值。選擇這q個受限制的值的方案數為:

C x q 2 q

即選擇q個限制對,每個限制對有兩種選擇。
一樣的令Xi=有多少個數的值為i,則就是求解下面方程的解數:

i = 1 q + y X i = z

但是由於我們必須選擇受限制的數,所以如果i受限制,則 X i >= 1 ;否則 X i >= 0
我們一樣通過給所有滿足 X i >= 0 的Xi加上1進行問題的轉化。則問題變為求解下面方程的解數:

i = 1 q + y X i = z + y X >= 1

它的解數為 C z + y 1 q + y 1

因此, f ( x , y , z ) = q = 0 q <= x q <= z C z + y 1 q + y 1 C x q 2 q
注意特判 q+y-1<0 的情況。

@程式碼@

如果有什麼問題或疑惑的地方可以參考程式碼或評論在下面,我會認真回覆的qwq。

#include<cstdio>
const int MOD = 998244353;
const int MAXN = 4000;
int C[MAXN + 5][MAXN + 5];
int pw2[MAXN + 5];
void init() {
    C[0][0] = 1; pw2[0] = 1;
    for(int i=1;i<=MAXN;i++) {
        C[i][0] = 1;
        for(int j=1;j<=i;j++) {
            C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
        }
        pw2[i] = pw2[i-1] * 2 % MOD;
    }
}
int solve(int x, int y, int z) {
    int ret = 0;
    for(int i=0;i<=z&&i<=x;i++)
        if( y+i-1 >= 0 ) ret = (ret + 1LL*pw2[i]*C[x][i]%MOD*C[z+y-1][y+i-1]%MOD) % MOD;
    return ret;
}
int main() {
    init();
    int N, K;
    scanf("%d%d", &K, &N);
    for(int i=2;i<=2*K;i++) {
        int cnt = 0;
        for(int j=1;j<=K;j++)
            if( 1 <= i-j && i-j <= K ) cnt++;
        if( i % 2 == 0 ) {
            printf("%d\n", (solve((cnt-1)/2, K-cnt, N) + solve((cnt-1)/2, K-cnt, N-1)) % MOD);
        }
        else {
            printf("%d\n", solve(cnt/2, K-cnt, N));
        }
    }
}

@[email protected]

就是這樣,新的一天裡,也請多多關照哦(ノω<。)ノ))☆.。~