[國家集訓隊]Crash的數字表格
阿新 • • 發佈:2021-01-08
題意
求這個\(\sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{m}lcm(i,j) \mod (20101009)\)
想法
以下\(n > m\)
在物理課上推出了柿子(逃
回家了拍草稿紙上來
\(\sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{m}lcm(i,j)\)
不想寫一大堆的\(LaTex\)下面寫出的等式都是連等的
\(\sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{m}lcm(i,j)\)
\(\sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{m}\frac{i*j}{gcd(i,j)}\)
改為列舉\(gcd(i,j) = d\)
\(\sum\limits_{d = 1}^{n}\sum\limits_{i = 1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j = 1}^{\lfloor\frac{m}{d}\rfloor}i * j * d * [gcd(i,j) == 1]\)
再用莫反的套路
\(\sum\limits_{d = 1}^{n}\sum\limits_{i = 1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j = 1}^{\lfloor\frac{m}{d}\rfloor}\sum\limits_{s|gcd(i,j)}i * j * d*\mu(s)\)
分類一下
\(\sum\limits_{d = 1}^{n}d\sum\limits_{i = 1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j = 1}^{\lfloor\frac{m}{d}\rfloor}\sum\limits_{s|gcd(i,j)}i * j * \mu(s)\)
再把後三個求和改為列舉\(s\)
\(\sum\limits_{d = 1}^{n}d\sum\limits_{s}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{i = 1}^{\lfloor\frac{n}{ds}\rfloor}\sum\limits_{j = 1}^{\lfloor\frac{m}{ds}\rfloor}i * j * \mu(s) * s^2\)
\(\sum\limits_{d = 1}^{n}d\sum\limits_{s}^{\lfloor\frac{n}{d}\rfloor}\mu(s) * s^2\sum\limits_{i = 1}^{\lfloor\frac{n}{ds}\rfloor}i\sum\limits_{j = 1}^{\lfloor\frac{m}{ds}\rfloor}j\)
後面兩個求和用等差公式
此時這個柿子是\(O(n^2)\)的
接下來的步驟為了降低複雜度
\(\sum\limits_{d = 1}^{n}d * s\sum\limits_{s}^{\lfloor\frac{n}{d}\rfloor}\mu(s) * s\sum\limits_{i = 1}^{\lfloor\frac{n}{ds}\rfloor}i\sum\limits_{j = 1}^{\lfloor\frac{m}{ds}\rfloor}j\)
改列舉\(T = d * s\)
\(\sum\limits_{T = 1}^{n}T\sum\limits_{i = 1}^{\lfloor\frac{n}{T}\rfloor}i\sum\limits_{j = 1}^{\lfloor\frac{m}{T}\rfloor}j\sum\limits_{s|T}s*\mu(s)\)
這樣中間兩個求和是\(O(1)\)最後那個求和我們可以在篩\(\mu\)時一併篩出\(\mu(s)*s\)然後用狄利克雷字首和
複雜度\(O(n + N)\)
程式碼
#include<iostream>
#include<cstdio>
#define ll long long
ll n,m,mod = 20101009;
ll mu[10000010],p[10000010],f[10000010],tot;
bool v[10000010];
int N = 1e7,cnt;
void pre(){
f[1] = mu[1] = 1;
for(int i = 2;i <= 1e7;++i){
if(!v[i]) mu[i] = -1,p[++tot] = i;
f[i] = (mu[i] * i + mod) % mod;
for(int j = 1;j <= tot && i * p[j] <= 1e7;++j){
v[p[j] * i] = 1;
if(i % p[j] == 0){
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = -mu[i];
}
}
f[1] = 1;
for(int j = 1;j <= tot;++j)
for(int i = 1;i * p[j] <= 1e7;++i)
(f[i * p[j]] += f[i]) %= mod;
}
ll ans = 0;
ll sum(int x){
ll ans = 1ll * x * f[x] % mod;
ans = ans * 1ll * ((n / x + 1) * (n / x) / 2 % mod) % mod;
ans = ans * 1ll * ((m / x + 1) * (m / x) / 2 % mod) % mod;
return ans % mod;
}
int main(){
scanf("%lld%lld",&n,&m);
if(m > n)
std::swap(m,n);
pre();
for(int i = 1;i <= n;++i)
ans = (ans + sum(i)) % mod;
std::cout<<ans<<std::endl;
}