JZOJ6912.数论(math)
题目大意
求\(\sum_\limits{i=1}^n\sum_\limits{j=1}^{m}\gcd^n(i,j)\sum_\limits{k=1}^{ij}[\gcd(ij,k)=1]k\), 其中\(n,m<=10^7\).
求解过程
先化式子, 由\(\sum_\limits{i=1}^n[\gcd(i,n)=1]i=\frac{\varphi(n)n+[n=1]}{2}\)得原式等于
一定会枚举到\(ij=1\),所以把\(ij\)等于\(1\)的\(\frac{1}{2}\)的贡献提出来.
由\(\varphi(ij)=\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\)(证明可以考虑质因子对每一个因式的贡献)得
考虑设\(d=\gcd(i,j)\)并枚举\(d\).
看到后面的\([\gcd(i,j)=d]\)就想繁衍反演一下:(设\(u|\frac{\gcd(i,j)}{d}\), 不要忘记\(i<=n\),\(j<=m\))
把\(u\)提到前面来,注意变换求和号的条件:
设\(T=du\),
啊这个时候有同学就要说了:那中间这个\(\sum_\limits{T|i}i\varphi(i)\)和\(\sum_\limits{T|j}j\varphi(j)\)就一样了嘛!非也!不要忘了\(i,j\)的范围是不一样的!
对于这两个式子,我们可以通过高维前缀和在\(O(n\log\log{n})\)的时间内求解. 对于后面的\(\sum_\limits{d|T}\frac{d^{n+1}}{\varphi(d)}\mu(\frac{T}{d})\)可以线性筛.
具体地,我们设:
\(f(T)=\sum_\limits{d|T}\frac{d^{n+1}}{\varphi(d)}\mu(\frac{T}{d})\)
很明显地有:
-
\(f\)是积性函数
-
\(f(1)=1\)
-
\(f(p)=\frac{p^{n+1}}{p-1}-1\)
-
\(f(p^c)=\frac{p^{c(n+1)}}{p^c-p^{c-1}}-\frac{p^{(c-1)(n+1)}}{p^{c-1}-p^{c-2}}(c>1)\) 不是很显然, 可以考虑\(\mu(\frac{T}{d})\)只会在\(\frac{T}{d}=1\)和\(\frac{T}{d}=p\)的时候有值
-
根据4有\(f(p^{c+1})=p^nf(p^c)(c>2)\)
综上, 我们可以在线筛的时候处理出\(f(n)\), 当一个质因子的次数大于2时, 直接递推即可; 等于2时, 考虑线筛预处理出每个素数的\(f(p^2)\)和\(f^{-1}(p)\)即可. 等于1时,直接乘上\(f(p)\)即可.
结合两个算法可以在\(O(n\log\log{n})\)的时间内求解本题.
代码:
#include <cstdio>
#include <cstring>
#define P 670000
#define N 10000010
#define MOD 998244353
#define init(a, b) memset(a, b, sizeof(a))
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
#define fd(i, a, b) for(int i = (a); i >= (b); --i)
using namespace std;
inline int qpow(int a, int b){int ret = 1; for(; b; b >>= 1, a = 1ll * a * a % MOD) b & 1 && (ret = 1ll * ret * a % MOD); return ret;}
int n, m, mx, mn, c, ans, p[P], fpinv[P], fp2[P], inv[N], pw[P], phi[N], f[N], sn[N], sm[N];
bool v[N];
int main()
{
freopen("math.in", "r", stdin);
freopen("math.out", "w", stdout);
scanf("%d %d", &n, &m);
mx = n > m ? n : m; mn = n + m - mx;
inv[1] = f[1] = phi[1] = 1;
fo(i, 2, mx) inv[i] = 1ll * (MOD - MOD / i) * inv[MOD % i] % MOD;
fo(i, 2, mx)
{
if(!v[i])
p[++c] = i, pw[c] = qpow(i, n + 1), phi[i] = i - 1,
fpinv[c] = qpow(f[i] = (1ll * pw[c] * inv[i - 1] % MOD - 1 + MOD) % MOD, MOD - 2),
fp2[c] = 1ll * pw[c] * (1ll * pw[c] * inv[i] % MOD - 1 + MOD) % MOD * inv[i - 1] % MOD;
for(int j = 1; j <= c && p[j] * i <= mx; ++j)
{
v[i * p[j]] = 1;
if(!(i % p[j]))
{
phi[i * p[j]] = phi[i] * p[j];
if(!((i / p[j]) % p[j])) f[i * p[j]] = 1ll * f[i] * pw[j] % MOD * inv[p[j]] % MOD;
else f[i * p[j]] = 1ll * f[i] * fpinv[j] % MOD * fp2[j] % MOD;
break ;
}
phi[i * p[j]] = phi[i] * phi[p[j]];
f[i * p[j]] = 1ll * f[i] * f[p[j]] % MOD;
}
}
fo(i, 1, n) sn[i] = 1ll * phi[i] * i % MOD;
fo(i, 1, m) sm[i] = 1ll * phi[i] * i % MOD;
fo(i, 1, c)
{
fd(j, n / p[i], 1) sn[j] = (sn[j] + sn[j * p[i]]) % MOD;
fd(j, m / p[i], 1) sm[j] = (sm[j] + sm[j * p[i]]) % MOD;
}
fo(i, 1, mn)
ans = (ans + 1ll * sn[i] * sm[i] % MOD * f[i] % MOD) % MOD;
ans = 1ll * (ans + 1) * qpow(2, MOD - 2) % MOD;
printf("%d", ans);
return 0;
}
浙公网安备 33010602011771号