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)\),随便过。