[Tsinsen A1300]JZPKIL
卡常的题见过,这么变态的卡常题……可能出题人过于文明,,,下面是卡常记录的一部分:
下面开始颓式子:
[BZOJ 3601]一个人的数论
本来想做JZPKIL的……但卡常太恶心了
上来先颓式子:
\[
\DeclareMathOperator{\id}{id}
\begin{aligned}
f_d(n) &= \sum_{i = 1}^n [(i, n) = 1]i^d\\
&= \sum_{i = 1}^n i^d\sum_{k | n, k | i}\mu(k)\\
&= \sum_{k | n}\mu(k)\sum_{i = 1}^{\frac{n}{k}} (ik)^d\\
&= \sum_{k | n}\mu(k)k^d h_d(\frac{n}{d})\\
&= ((\mu\cdot\id^k)\ast h_d)
\end{aligned}
\]
其中\(h_d\)表示指数为\(d\)时的等幂求和函数。然后我们可能会想,如果这个函数是积性函数,那么我们可以对质因数分解的每一种质因数都求一遍答案,而由于\(\mu\)的存在(对于质数的幂\(p^k\)的因数,只有\(1\)和\(p\)的莫比乌斯函数值不为0),所以需要处理的情况只有两种。
不过很可惜,\(h_d\)显然不是积性函数,所以最后的整个卷积也不是积性函数。但是我们注意到\(h_d\)事一个\(d + 1\)次多项式,所以我们可以把多项式每一项都当成单独的函数,然后每个单独函数卷出来都是一个积性函数。至于求多项式每一项的系数,用伯努利数即可。
代码:
/************************************************************** Problem: 3601 User: danihao123 Language: C++ Result: Accepted Time:220 ms Memory:948 kb ****************************************************************/ #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <utility> typedef long long ll; ll ha = 1000000007LL; ll pow_mod(ll a, ll b) { ll ans = 1LL, res = a; while(b) { if(1LL & b) ans = (ans * res) % ha; res = (res * res) % ha; b >>= 1; } return ans; } ll inv(ll x) { return pow_mod(x, ha - 2LL); } const int maxn = 105; ll C[maxn][maxn]; void process_C() { C[0][0] = 1LL; for(int i = 1; i < maxn; i ++) { C[i][0] = C[i][i] = 1LL; for(int j = 1; j < i; j ++) { C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % ha; } } } ll B[maxn]; void process_B() { B[0] = 1LL; for(int i = 1; i <= 101; i ++) { B[i] = 1LL; for(int j = 0; j < i; j ++) { ll d = (((C[i][j] * B[j]) % ha) * inv(i - j + 1)) % ha; B[i] = (B[i] - d + ha) % ha; } } } const int maxw = 1005; typedef std::pair<ll, ll> pii; pii P[maxw]; ll dv[maxw][3]; int d, w; void process_dv() { for(int i = 1; i <= w; i ++) { ll p = P[i].first, t = P[i].second; p %= ha; dv[i][0] = pow_mod(p, t); dv[i][1] = pow_mod(p, t - 1LL); dv[i][2] = pow_mod(p, d); } } ll calc(ll k, int z) { ll ans = k; for(int i = 1; i <= w; i ++) { ll p = P[i].first, t = P[i].second; p %= ha; ll f1 = pow_mod(dv[i][0], z), f2 = pow_mod(dv[i][1], z); ll v1 = (f1 - (dv[i][2] * f2) % ha + ha) % ha; ans = (ans * v1) % ha; } #ifdef LOCAL printf("Case (%lld, %d) : %lld\n", k, z, ans); #endif return ans; } int main() { process_C(); process_B(); scanf("%d%d", &d, &w); for(int i = 1; i <= w; i ++) { scanf("%lld%lld", &P[i].first, &P[i].second); } process_dv(); ll ans = 0LL; for(int i = 0; i <= d; i ++) { ll g = calc((((C[d + 1][i] * B[i]) % ha) * inv(d + 1)) % ha, d + 1 - i); ans = (ans + g) % ha; } printf("%lld\n", ans); return 0; }