AGC009E题解

赛时应该口胡了个大概,可惜没有转化成更纯粹的问题。

问题可以看做有多少不同的 \(x\) 满足 \(x=\sum_{i=1}^{m}(\frac{1}{k})^{a_i},1-x=\sum_{i=1}^{n}(\frac{1}{k})^{b_i}\)

以上结论可以将平均数的过程建成一棵树,然后 \(x\) 代表权值为 \(1\) 的叶子结点,\(y\) 代表权值为 \(0\) 的叶子结点。

然后将某个合法的数字 \(x\) 写成 \(k\) 进制小数

考虑 \(x\) 是怎么被树中的节点进位上来的,能够发现进位是让某一位减去 \(k\),然后下一位加上 \(1\),相当于让数位的总和减少了 \(k-1\)

所以设 \(x\) 表示的 \(k\) 进制小数为 \(0.c_1c_2...c_t\),那么有 \(\sum c_i\equiv n\bmod{k-1}\),并且显然有的是 \(\sum c_i\leq n\)

所以满足条件的 \(x\) 可以映射到一个序列上,这个序列满足 \(\sum a_i\equiv n\bmod{k-1},\sum a_i\leq n,1+\sum k-a_i-1\leq m\)

如果知道 \(a\) 序列的长度 \(len\) 那么可以知道 \(len\times(k-1)-m+1\leq\sum a_i\leq n\)

枚举 \(len\),问题变为了有多少个长度为 \(len\) 的序列 \(a\) 满足 \(\sum a_i\equiv n\bmod{k-1}\and L\leq \sum a_i\leq R\)

#include<cstdio>
const int M=3005,mod=1e9+7;
int n,m,k,x[M],F[M],G[M];
inline int max(const int&a,const int&b){
	return a>b?a:b;
}
signed main(){
	int ans(0);scanf("%d%d%d",&n,&m,&k);F[0]=1;
	for(int i=1;i*(k-1)<=n+m-1;++i){
		for(int L=max(i*(k-1)-m+1,0),j=n;j>=L;j-=k-1)for(int x=1;x<k&&j-x>=0;++x)ans=(ans+F[j-x])%mod;
		for(int j=0;j<=n;++j)for(int x=0;x<k&&j-x>=0;++x)G[j]=(G[j]+F[j-x])%mod;for(int j=0;j<=n;++j)F[j]=G[j],G[j]=0;
	}
	printf("%d",ans);
}

于是设 \(f[n][m]\) 表示和为 \(n\) 在模 \(k-1\) 意义下和为 \(m\)\(a\) 序列。

实际上压缩状态可以记 \(f[n][m]\) 表示模 \(k-1\) 意义下和为 \(n\) 并且进位了 \(m\) 次。状态数显然是 \(O(n)\) 的,暴力转移即可。

上面那个状态太傻逼了,直接记录 \(f[n]\) 表示和为 \(n\) 即可。

转移一次复杂度 \(O(nk)\),但是因为做的是 \(\frac{n+m-1}{k-1}\) 所以复杂度是 \(O(n^2)\),随便过。

posted @ 2022-09-04 14:49  Prean  阅读(33)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};