题解:P11957 「ZHQOI R1」幂和
LostKeyToReach · · 题解
笑点解析:赛时使用封装的取模类导致
海亮是不是人均多项式代师啊。
这是一个不用动脑子的做法。我们不妨设答案为
这样只对
接下来我们对
考虑给
组合意义显然,那么第
参考代码:
VVI polys, polyss;
int n, x, k;
VI fact, ifact;
void prepare() {
polys.resize(46);
fact.resize(k + 1, 0);
ifact.resize(k + 1, 0);
fact[0] = 1;
For(i, 1, k) fact[i] = modMul(fact[i - 1], i);
For(i, 0, k) ifact[i] = power(fact[i], mod - 2);
For(i, 0, 45) {
polys[i].resize(k + 1, 0);
For(r, 0, k) {
if (r == 0) {
continue;
}
polys[i][r] = modMul(-power(2, i * r), ifact[r]);
}
}
polyss.resize(46);
polyss[0].resize(k + 1, 0);
polyss[0][0] = 1;
For(i, 0, 44) polyss[i + 1] = convolution(polyss[i], polys[i], k);
}
int calc(int m, int x, int kk) {
int ans = 0;
For(j, 0, kk) {
ans = modAdd(ans, modMul(modMul(modMul(modMul(modMul(fact[k], ifact[j]),
ifact[k - j]), power(x, kk - j)), polyss[m][j]), fact[j]));
}
return ans;
}
std::map<PII, int> mp;
int solve(int n, int x) {
if (n == -1) return 0;
if (mp.find({n, x}) != mp.end())
return mp[{n, x}];
int m = 64 - __builtin_clzll(n + 1) - 1;
int p = 1LL << m;
if (n == p - 1) return mp[{n, x}] = calc(m, x, k);
else {
return mp[{n, x}] = modSub(calc(m, x, k), solve(n - p, (x + p) % mod));
}
}
#define MULTI_TEST 0
int32_t main() {
#if MULTI_TEST == 1
#else
std::cin >> n >> x >> k;
prepare();
std::cout << solve(n, x) << "\n";
#endif
}