GMOJ 6833 justice 题解
GMOJ 6833 justice 题解
我们发现取平均数是一个树形结构,那么把树画出来后,每个叶子节点对答案的贡献为\(v_i\cdot(\frac 1 k)^{dep_i}\),假若每个点的权值均为1,则答案为1,
则x点所有贡献之和可以看作一个k进制小数\(u=\sum \frac {c_i} {k^i}\),如果没有进位,则\(\sum c_i = n\),每进位一次,\(\sum c_i\)减k-1,所以考虑进位则\(\sum c_i \equiv n \pmod {k-1}\)同理,y点的贡献之和也可看作一个小数\(v = 1 - u\),则各个数位之和为\(k\cdot len-\sum c_i - i+1\)
注意当\(x=y\)时答案为1
为什么\(x\ne y\)时不会重复统计?因为当\(u\)不同时
\[ans=u\cdot x+v\cdot y = u \cdot x + y - u \cdot y = u\cdot (x-y) + y
\]
一定不同。
#include <cstdio>
#define INC(x, y) (x = (x+(y))%mods)
using namespace std;
typedef long long ll;
const int maxn=3000, maxk=3000, mods=1000000007;
int main() {
freopen("justice.in", "r", stdin);
freopen("justice.out", "w", stdout);
static ll f[maxn+1][2], suf[maxn+1];
int m, n, k, x, y, len;
scanf("%d %d %d %d %d", &m, &n, &k, &x, &y);
if (x==y) {
printf("1\n");
return 0;
}
ll ans=0;
len = (m+n-1)/(k-1);
f[0][0] = 1;
for (int i=1; i<=len; i++) {
suf[0] = 0;
for (int j=0; j<=n; j++) {
suf[j] = (j ? suf[j-1] : 0) + f[j][0];
f[j][0] = (suf[j] - (j>=k ? suf[j-k] : 0) + mods) % mods;
f[j][1] = (suf[j-1] - (j>=k ? suf[j-k] : 0) + mods) % mods;
if (j && (i*k-i+1-j) && j%(k-1)==n%(k-1) && i*k-i+1-j<=m) {
INC(ans, f[j][1]);
}
}
}
printf("%lld\n", ans);
fclose(stdin);
fclose(stdout);
return 0;
}