[湖北省队互测2014]一个人的数论
给 \(n\) 的唯一分解,求 \([1,n]\) 中与 \(n\) 互质的数的 \(k\) 次方和。
先考虑莫反:
\[\sum_{i=1}^n [gcd(i,n)==1]i^k
\]
\[\sum_{i=1}^n i^k \sum_{d|gcd(i,n) \mu(d)}
\]
\[\sum_{d|n} \mu(d)\sum_{d|i} i^k
\]
\[\sum_{d|n} d^k\mu(d)\sum_{i=1}^{n\over d} i^k
\]
到此可以获得40分的好成绩。
发现后面是个多项式,我们可以拉插/消元/伯努利数搞出系数,设:
\[f(x)=\sum_{i=1}^x i^k=\sum_{i=0}^{k+1} a_ix^i
\]
那么原来的式子可以变成:
\[\sum_{d|n} d^k \mu(d)\sum_{i=0}^{k+1} a_i({n\over d})^i
\]
\[\sum_{i=0}^{k+1}a_i \sum_{d|n} \mu(d)d^k({n\over d})^i
\]
后面那一坨实际上是一个关于 \(n\) 的积性函数(积性函数的狄利克雷卷积还是积性函数),我们只用考虑 \(n=p^t\) 的情况,而 \(n\) 的唯一分解一开始就给出,直接乘起来就可以。
先把 \(n=p^t\) 代入式子
\[\sum_{d|p^t} \mu(d)d^k({p^t\over d})^i
\]
\[\sum_{j=0}^t \mu(p^j)p^{jk+i(t-j)}
\]
注意到当 \(j>=2\) 时,\(\mu(p^j)=0\),对答案没有贡献,所以上式等于
\[p^{it}-p^{k+i(t-1)}
\]
于是就写完了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 2e3 + 5, M = 205, mod = 1e9 + 7;
#define int long long
int p[N], a[N], d[N], g[M][M], f[M], w, k;
inline int power(int a, int b) {
int t = 1, y = a, k = b;
while (k) {
if (k & 1) t = (1ll * t * y) % mod;
y = (1ll * y * y) % mod; k >>= 1;
} return t;
}
inline void getf() {
for (int i = 1; i <= k + 3; ++i) {
g[i][1] = 1; //cout << 1 << ' ';
for (int j = 2; j <= k + 3; ++j)
g[i][j] = (1ll * g[i][j - 1] * i) % mod;//, cout << g[i][j] << ' ';
g[i][k + 4] = (g[i - 1][k + 4] + power(i, k));// cout << g[i][k + 4] << endl;
if (g[i][k + 4] >= mod) g[i][k + 4] -= mod;
}
for (int i = 1; i <= k + 3; ++i) {
int p = i;
for (int j = i; j <= k + 3; ++j)
if (g[j][i] == g[p][i]) p = i;
for (int j = 1; j <= k + 4; ++j) swap(g[i][j], g[p][j]);
for (int j = i + 1; j <= k + 4; ++j) g[i][j] = (1ll * g[i][j] * power(g[i][i], mod - 2)) % mod;
for (int j = 1; j <= k + 3; ++j)
if (i != j)
for (int l = i + 1; l <= k + 4; ++l)
g[j][l] = ((g[j][l] - (1ll * g[j][i] * g[i][l] % mod)) % mod + mod) % mod;
} for (int i = 1; i <= k + 3; ++i) f[i] = g[i][k + 4];
}
signed main() {
scanf("%lld%lld", &k, &w);
getf(); int ans = 0; int del;
for (int i = 1; i <= w; ++i)
scanf("%lld%lld", &p[i], &a[i]);
for (int i = 0; i < k + 3; ++i) {
del = 1; int num;
for (int j = 1; j <= w; ++j) {
num = power(p[j], (1ll * i * a[j]) % (mod - 1)) - power(p[j], k + (1ll * (a[j] - 1) * i) % (mod - 1)) % mod;
del = (1ll * del * num) % mod;
}
del = (1ll * del * f[i + 1]) % mod;
ans = (ans + del) % mod;
if (ans < 0) ans += mod;
} printf("%lld", ans);
return 0;
}

浙公网安备 33010602011771号