Examples

2022-7-18 & 19 & 20 #15 AGC052C

遇到简单 div.2,结果 D 写了一个巨大复杂的做法,调了 114 年没过。。。D1 还 fst 了。。。

为啥我会觉得优先队列 pop 清空内存而 vector swap 空指针不清空内存啊。。。

039 AGC052C Nondivisible Prefix Sums

首先考虑如何判定。(一个显然的条件是全局和不为 \(P\) 的倍数)

由于前缀和为 \(0\) 的限制是很松的,我们只要还有两个数就能避免不合法。于是考虑一种贪心策略:能填出现最多的数字就填它,否则填次大的。

不妨令出现最多的数字为 \(1\),否则我们可以将所有数乘上其逆元。那么我们一定是不断填 \(1\) 直到 \(P-1\),于是有:

\[tot_1\leqslant \sum_{i=1}^n[a_i\ne 1](P-a_i)+P-1 \]

右边很大,而左边很小,不妨容斥计算不合法的方案数。

\(f_{i,j}\) 表示长度为 \(i\) 的序列,右式值为 \(j\) 的方案数,可以发现 dp 状态也能表示是否合法:

\[f_{i,j}=\sum_{k=1}^{\min(p-2,j)}f_{i-1,j-k} \]

前缀和优化即可,最后用组合数随便算算,复杂度 \(O(n^2)\)

#include<stdio.h>
const int maxn=5005,mod=998244353;
int n,P,ans;
int C[maxn][maxn],f[maxn][maxn],sum[maxn],g[maxn];
int main(){
	scanf("%d%d",&n,&P);
	for(int i=0;i<=5000;i++){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
	}
	g[0]=0;
	for(int i=1,mul=1;i<=n;i++,mul=1ll*mul*(P-1)%mod)
		g[i]=(1ll*(P-2)*g[i-1]+1ll*(P-1)*(mul-g[i-1]+mod))%mod;
	f[0][0]=1;
	for(int i=1;i<=n;i++){
		sum[0]=f[i-1][0];
		for(int j=1;j<=n;j++)
			sum[j]=(sum[j-1]+f[i-1][j])%mod;
		for(int j=1;j<=n;j++)
			f[i][j]=(sum[j-1]-(j-(P-2)>0? sum[j-(P-2)-1]:0)+mod)%mod;
	}
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++)
			if((n-i)%P-j%P!=0&&n-i>j+(P-1))
				ans=(ans+1ll*f[i][j]*C[n][i])%mod;
	printf("%d\n",(g[n]-1ll*(P-1)*ans%mod+mod)%mod);
	return 0;
}

不如接受自己的颓怪事实。

posted @ 2022-07-19 02:24  xiaoziyao  阅读(81)  评论(0)    收藏  举报