AtCoder Beginner Contest 217G
从小清新题目开始的康复之旅
G - Groups
Problem Statement
You are given positive integers $N$ and $M$. For each $k=1,…,N$, solve the following problem.
- Problem: We will divide $N$ people with ID numbers $1$ through $N$ into $k$ non-empty groups. Here, people whose ID numbers are equal modulo $M$ cannot belong to the same group.
How many such ways are there to divide people into groups?
Since the answer may be enormous, find it modulo $998244353$.
Here, two ways to divide people into groups are considered different when there is a pair $(x,y)$ such that Person $x$ and Person $y$ belong to the same group in one way but not in the other.
Constraints
- $2≤N≤5000$
- $2≤M≤N$
- All values in input are integers.
题目分析
一个组合数学题
一开始想简单了,以为是一个最简单的容斥,考虑最多分成n组的情况减去最多分成n-1组的情况,以为这个就是恰好n组的情况
递推地看第n项的答案f(n),首先钦定某一个剩余类$a_1$的位置,其余的剩余类$a_j$随意插空有$Pi A(n, a_j)$种方案,然后减去恰好包含$n-1$项$f(n-1)*A(n-a_1,(n-1)-a_1)$,$n-2$项$f(n-2)*A(n-a_1,(n-2)-a_1)$...的方案。最后因为方案是无序的,再除以$(n-a_1)!$
CE了一发emmm根本没想起来atcoder不能用万能头
// #include<bits/stdc++.h> #include<cstdio> const int MO = 998244353; const int maxn = 5035; int n,m,a[maxn],f[maxn],fac[maxn],inv[maxn]; int A(int n, int m) { return 1ll*fac[n]*inv[n-m]%MO; } int C(int n, int m) { return 1ll*fac[n]*inv[n-m]%MO*inv[m]%MO; } void Inc(int &x, int y) { x = (x+y+MO)%MO; } void Dec(int &x, int y) { x = (x-y+MO)%MO; } int main() { scanf("%d%d",&n,&m); for (int i=1; i<=n%m; i++) a[i] = n/m+1; for (int i=n%m+1; i<=m; i++) a[i] = n/m; inv[0] = inv[1] = fac[1] = 1; for (int i=2; i<=n; i++) inv[i] = 1ll*(MO-MO/i)*inv[MO%i]%MO; for (int i=2; i<=n; i++) inv[i] = 1ll*inv[i-1]*inv[i]%MO, fac[i] = 1ll*fac[i-1]*i%MO; for (int i=1; i<a[1]; i++) f[i] = 0; for (int i=a[1]; i<=n; i++) { int cnt = 1; for (int j=2; j<=m; j++) cnt = 1ll*cnt*A(i, a[j])%MO; Inc(f[i], cnt); for (int j=a[1]; j<i; j++) Dec(f[i], 1ll*f[j]*A(i-a[1], j-a[1])%MO); f[i] = 1ll*f[i]*inv[i-a[1]]%MO; } for (int i=1; i<=n; i++) printf("%d ",f[i]); return 0; }
END