P6156 简单题
推式子
∑i=1n∑j=1n(i+j)kf(gcd(i,j))gcd(i,j)=∑i=1n∑j=1n(i+j)kμ2(gcd(i,j))gcd(i,j)=∑d=1nμ2(d)dk+1∑i=1nd∑j=1nd(i+j)k(gcd(i,j)==1)=∑d=1nμ2(d)dk+1∑p=1ndp2μ(p)∑i=1npd∑j=1npd(i+j)kt=pd,f(n)=∑i=1n∑j=1n(i+j)k=∑t=1nf(nt)tk∑d∣tμ2(d)μ(td)d\sum_{i = 1} ^{n} \sum_{j = 1} ^{n}(i + j) ^ kf(gcd(i, j))gcd(i, j)\\ = \sum_{i = 1} ^{n} \sum_{j = 1} ^{n} (i + j) ^ k \mu ^ 2(gcd(i, j)) gcd(i, j)\\ = \sum_{d = 1} ^{n} \mu ^ 2 (d) d ^ {k + 1} \sum_{i = 1} ^{\frac{n}{d}} \sum_{j = 1} ^{\frac{n}{d}} (i + j) ^ k (gcd(i, j) == 1)\\ = \sum_{d = 1} ^{n} \mu ^ 2(d) d ^ {k + 1} \sum_{p = 1} ^{\frac{n}{d}} p ^ 2 \mu(p) \sum_{i = 1} ^{\frac{n}{pd}} \sum_{j = 1} ^{\frac{n}{pd}} (i + j) ^ k\\ t = pd, f(n) = \sum_{i = 1} ^{n} \sum_{j = 1} ^{n} (i + j) ^ k \\ = \sum_{t = 1} ^{n} f(\frac{n}{t})t ^ k \sum_{d \mid t} \mu ^ 2(d) \mu(\frac{t}{d}) d\\ i=1∑nj=1∑n(i+j)kf(gcd(i,j))gcd(i,j)=i=1∑nj=1∑n(i+j)kμ2(gcd(i,j))gcd(i,j)=d=1∑nμ2(d)dk+1i=1∑dnj=1∑dn(i+j)k(gcd(i,j)==1)=d=1∑nμ2(d)dk+1p=1∑dnp2μ(p)i=1∑pdnj=1∑pdn(i+j)kt=pd,f(n)=i=1∑nj=1∑n(i+j)k=t=1∑nf(tn)tkd∣t∑μ2(d)μ(dt)d
我们先对f(n)f(n)f(n)分析:
假定a(n)=∑i=1nik,b(n)=∑i=1n∑j=1ijk=∑i=1na(i)简单化简一下就可以得到f(n)=b(2n)−2b(n)显然我们可以通过欧拉筛得到ik,然后一次前缀和得到a(i),再一次前缀和得到b(i)假定a(n) = \sum_{i = 1} ^{n} i ^ k,b(n) = \sum_{i = 1} ^{n} \sum_{j = 1} ^{i} j ^ k = \sum_{i = 1} ^{n} a(i) \\ 简单化简一下就可以得到f(n) = b(2n) - 2b(n)\\ 显然我们可以通过欧拉筛得到i ^ k,然后一次前缀和得到a(i), 再一次前缀和得到b(i)\\ 假定a(n)=i=1∑nik,b(n)=i=1∑nj=1∑ijk=i=1∑na(i)简单化简一下就可以得到f(n)=b(2n)−2b(n)显然我们可以通过欧拉筛得到ik,然后一次前缀和得到a(i),再一次前缀和得到b(i)
接下来我们对f(n)=∑d∣nμ2(d)μ(nd)df(n) = \sum_{d \mid n} \mu^ 2(d) \mu(\frac{n}{d})df(n)=∑d∣nμ2(d)μ(dn)d分析:
显然这是一个积性函数,所以f(n)=f(pk)f(npk),当k=0,f(1)=1,当k=1,f(p)=p−1,当k=2,f(p2)=−p,当k>=3,显然对任意一项d,或者nd一定有一项存在平方项,所以μ会变成0,所以k>=3f(pk)=0所以这个积性函数我们只要在欧拉筛中特判处理一下即可。显然这是一个积性函数,所以f(n) = f(p ^ k) f(\frac{n}{p ^ k}),\\ 当k = 0, f(1) = 1,\\ 当k = 1, f(p) = p - 1,\\ 当k = 2, f(p ^ 2) = -p,\\ 当k >= 3,显然对任意一项d,或者\frac{n}{d}一定有一项存在平方项,所以\mu会变成0,\\ 所以k >= 3 f(p ^ k) = 0\\ 所以这个积性函数我们只要在欧拉筛中特判处理一下即可。 显然这是一个积性函数,所以f(n)=f(pk)f(pkn),当k=0,f(1)=1,当k=1,f(p)=p−1,当k=2,f(p2)=−p,当k>=3,显然对任意一项d,或者dn一定有一项存在平方项,所以μ会变成0,所以k>=3f(pk)=0所以这个积性函数我们只要在欧拉筛中特判处理一下即可。
代码
P6222 「P6156 简单题」加强版
这道题目的加强版本,由于我这里采用的是线性复杂度的算法,所以只要稍加修改即可过这道题。
/*Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1using namespace std;typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;inline ll read() {ll f = 1, x = 0;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f * x;
}const int N = 1e7 + 10, mod = 998244353;int prime[N], cnt;ll f[N], pw[N], n, k;bool st[N];ll quick_pow(ll a, ll n) {ll ans = 1;while(n) {if(n & 1) ans = ans * a % mod;a = a * a % mod;n >>= 1;}return ans;
}void init() {f[1] = pw[1] = 1;for(int i = 2; i < N; i++) {if(!st[i]) {prime[cnt++] = i;f[i] = i - 1;pw[i] = quick_pow(i, k);}for(int j = 0; j < cnt && i * prime[j] < N; j++) {pw[i * prime[j]] = pw[i] * pw[prime[j]] % mod;st[i * prime[j]] = 1;if(i % prime[j] == 0) {int temp = i / prime[j];if(temp % prime[j]) f[i * prime[j]] = (mod - 1ll * prime[j] * f[temp] % mod) % mod;break;}f[i * prime[j]] = f[i] * f[prime[j]] % mod;}}for(int i = 1; i < N; i++) f[i] = (f[i - 1] + f[i] * pw[i] % mod) % mod, pw[i] = (pw[i] + pw[i - 1]) % mod;for(int i = 1; i < N; i++) pw[i] = (pw[i] + pw[i - 1]) % mod;
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);n = read(), k = read(), init();ll ans = 0;for(ll l = 1, r; l <= n; l = r + 1) {r = n / (n / l);ans = (ans + (f[r] - f[l - 1] + mod) % mod * (((pw[2 * (n / l)] - 2 * pw[n / l]) % mod + mod) % mod) % mod) % mod;}printf("%lld\n", ans);return 0;
}