【Atcoder - ARC102E】Stop. Otherwise...

版权声明:本文为博主原创文章……懂吗?要尊重别人的劳动成果呐 https://blog.csdn.net/Tiw_Air_Op1721/article/details/82347098

@Stop. Otherwise…@


@题目描述 - English@

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

@END@

就是这样,新的一天里,也请多多关照哦(ノω<。)ノ))☆.。~

猜你喜欢

转载自blog.csdn.net/Tiw_Air_Op1721/article/details/82347098
今日推荐