[DP记录]AT2294 [AGC009E] Eternal Average
command_block
2021-04-27 16:46:42
**题意** : 黑板上有 $n$ 个 $0$ 和 $m$ 个 $1$ ,每次可以选择 $k$ 个数字将其擦除,然后把它们的平均数写上去。
保证 $n+m-1$ 能被 $k-1$ 整除。于是,这样一直操作最终只会剩下一个数字,问这个数字有多少种不同的可能。
答案对 $10^9+7$ 取模。
$n,m,k\leq 2000$ ,时限 $\texttt{2s}$。
------------
神必题。
将操作刻画为 $k$ 叉树。每次将新产生的节点与擦除的 $k$ 个节点连边,点权为直接儿子的平均数。
记 $m$ 个 $1$ 的深度分别为 $d_{1\sim m}$ (根的深度为 $0$),则最终的数为 $z=\sum\limits_{i=1}^mk^{-d_i}$。
将 $z$ 写作 $k$ 进制小数 $0.z_1z_2z_3...z_t$ ,其中 $z_t\neq 0$。
问题变为 : 有多少个 $k$ 进制小数可以生成合法的操作树。
我们知道,假如所有叶子都是 $1$ ,则根节点的点权一定是 $1$。
设 $m$ 个 $0$ 的深度为 $d'_{1\sim n}$ ,则有 $1=\sum\limits_{i=1}^mk^{-d_i}+\sum\limits_{i=1}^nk^{-d'_i}$。这是一个必要条件。
实际上,这个条件同时也是充分的 : 将 $z'=\sum\limits_{i=1}^nk^{-d'_i}$ 写成小数,最后一位一定和 $z$ 的最后一位和为 $k$ 而产生进位,然后再次必须和为 $k$。
根据这个过程不难构造出对应的树。
- 故问题转化为 :
求符合下列条件的实数 $z$ 的个数 :
- $z$ 可以写成 $m$ 个 $\frac{1}{k}$ 的幂的和。
- $1-z$ 可以写成 $n$ 个 $\frac{1}{k}$ 的幂的和。
对于 $k$ 进制小数 $z=0.z_1z_2z_3...z_t$ ,需要满足下列条件 :
- $0\leq z_i<k$
- $\sum_{i=1}^tz_i\leq n$
- $\sum_{i=1}^tz_i= n\pmod{k-1}$
- $1+\sum_{i=1}^t(k-1-z_i)\leq m$
- $1+\sum_{i=1}^t(k-1-z_i)= m\pmod{k-1}$
考虑 $\rm DP$。设 $dp[t][s][0/1]$ 表示填写了 $t$ 个数位,目前的数位和为 $s$ ,最后一个数是否为 $0$。(统计答案时钦定末位非 $0$)
边界为 $dp[0][0][0]=1$。
则有如下转移 :
$$dp[t][s][0]=dp[t-1][s][0]+dp[t-1][s][1]$$
$$dp[t][s][1]=\sum\limits_{c=1}^{k-1}dp[t-1][s-c][0]+dp[t-1][s-c][1]$$
利用前缀和优化即可 $O(1)$ 转移。
这里 $t$ 只会达到 $O(\frac{n+m}{k-1})$ 级别, $s$ 可以达到 $O\big(n\big)$ 级别。
于是复杂度为 $O\big((n+m)^2/k\big)$。
```cpp
#include<algorithm>
#include<cstdio>
#define MaxN 2050
using namespace std;
const int mod=1000000007;
int n,m,k,ans,dp[MaxN<<1][MaxN][2],o[MaxN];
int main()
{
scanf("%d%d%d",&n,&m,&k);
dp[0][0][0]=1;
for (int t=1;t<=(n+m)/(k-1);t++){
o[0]=(dp[t-1][0][0]+dp[t-1][0][1])%mod;
for (int s=1;s<=n;s++)
o[s]=((long long)o[s-1]+dp[t-1][s][0]+dp[t-1][s][1])%mod;
for (int s=0;s<=n;s++){
dp[t][s][0]=(dp[t-1][s][0]+dp[t-1][s][1])%mod;
if (s-k<0)dp[t][s][1]=o[s-1];
else dp[t][s][1]=(o[s-1]-o[s-k])%mod;
if (s%(k-1)==n%(k-1)&&1+t*(k-1)-s<=m&&(1+t*(k-1)-s)%(k-1)==m%(k-1))
ans=(ans+dp[t][s][1])%mod;
}
}printf("%d",(ans+mod)%mod);
return 0;
}
```