5813. 【NOIP提高A组模拟2018.8.14】 计算
Problem
Solution
正难则反.
考虑所有 的可能取值,那么最终组成的长度为 的序列,总共有
其中 表示 的约数个数.
那么考虑如果满足
然后把所有 变为 ,即可以得到
令 表示满足
表示满足
可以得到 .
如果现在可以算出
则可以很容易的计算最终答案的值了.
这个式子可以考虑把 分解质因数,那么对于每一个质数,其是互相独立的.
于是问题可以转化为你要构造一个长为 的序列 ,满足
然后这个显然可以用一个 的 去做,其中 表示序列长度, 表示每个位置最多能放多少个数。
但实际上,这样做太慢了,我们可以考虑容斥.
首先如果每个数的取值都是 ,且最终总和为 ,那么这是一个简单的挡板问题,方案数为
令 表示至少有 个数大于 的方案数.
然后考虑在总数 里减去 ,即把左边每个大于 的数的取值范围更新一下,使整个子问题能继续转化为挡板问题.
然后根据二项式反演,可以推得
所以容斥系数始终为 ,然后就可以解了.
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define M 100000
#define N 2000
#define T 210
#define mo 998244353
#define ll long long
#define F(i, a, b) for (ll i = a; i <= b; i ++)
#define G(i, a, b) for (ll i = a; i >= b; i --)
using namespace std;
ll ans, n, m, tot, sum, d, s2, z[M], bz[M], f[T][T * 30], jc[32 * M + 10], ny[32 * M + 10], g[M];
struct node { ll v, num; } q[N];
ll ksm(ll x, ll y) {
ll ans = 1;
for (; y; y >>= 1, x = (x * x) % mo)
if (y & 1) ans = (ans * x) % mo;
return ans;
}
ll C(ll n, ll m) {
return ((jc[n] * ny[m] % mo) * ny[n - m]) % mo;
}
int calc(ll q) {
ll ans = 0, yes = 1;
F(i, 0, 2 * m) {
g[i] = C(m * q - i * (q + 1) + 2 * m - 1, 2 * m - 1) * C(2 * m, i) % mo;
ans = (ans + yes * g[i]) % mo, yes = - yes;
}
return ans;
}
int main() {
freopen("count.in", "r", stdin);
freopen("count.out", "w", stdout);
scanf("%d %d", &n, &m);
jc[0] = ny[0] = 1;
F(i, 1, 32 * m) jc[i] = (jc[i - 1] * i) % mo; ny[32 * m] = ksm(jc[32 * m], mo - 2);
G(i, 32 * m - 1, 1) ny[i] = (ny[i + 1] * (i + 1)) % mo;
d = 2; int up = int(sqrt(n)) + 1;
F(i, 2, up) {
if (!bz[i]) z[++ z[0]] = i;
F( j, 1, z[0]) {
if (z[j] * i > up) break;
bz[i * z[j]] = 1;
if (i % z[j] == 0) break;
}
if (n % i == 0)
d += 2 - (i * i == n);
}
sum = ans = 1;
for (int i = 1; i <= z[0] && z[i] * z[i] <= n; i ++) {
int tot = 0;
while (n % z[i] == 0) tot ++, n /= z[i];
sum = (sum * (tot + 1)) % mo;
if (tot)
ans = (ans * calc(tot)) % mo;
}
if (n > 1)
sum = (sum * 2) % mo, ans = (ans * calc(1)) % mo;
sum = ksm(sum, 2 * m);
printf("%d\n", (((sum + ans) * ksm(2, mo - 2)) % mo + mo) % mo);
}
事实上,我们会发现,这里calc计算是 级别的,所以 可以开到 ,运用 在 分解质因数.
然后 可以开大到 级别.