题意:
求ΣΣlcm(i,j)
2693:多组询问
ans = ΣΣlcm(i,j) = ΣΣΣx*y*d (gcd(x,y) == 1) = ΣdΣΣx*y
令F[x][y] = ΣΣx*y(gcd(x,y) == 1)
莫比乌斯反演
F[x][y] = Σk^2*u(k)*sum[x/k][y/k]
sum[i][j] = ΣΣi*j
上式可以通过容斥证明
这样O(n)回答,,过2154
进一步优化
令D = kd
带进去,化化化化化
ans = Σsum[n/D][m/D]*ΣD*k*u(k) (k|D)
可以证明,g[k] = k*u(k) (k|D)是个积性函数
又,,积性函数的约数和也是积性函数
所以右边那坨是个积性函数,线性筛之
令h[D] = ΣD*k*u(k) (k|D)
筛法进行时 出现i%prime[j] == 0的情况时,和积性函数性质冲突
此时,令T = i*prime[j]
可以证明h[T] = prime[j]*h[i]
为什么呢?
因为T关于i,多出来的约数全部是满足u(k) = 0的
这部分忽略
而其它重合的东西
在ΣD*k*u(k) (k|D)中
有T = i*prime[j]啊
代码是两题互刷的,,,
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
using namespace std;
const int maxn = 1E7 + 10;
typedef long long LL;
const LL mo = 20101009;
LL n,m,k[maxn];
int tot,mu[maxn],prime[maxn];
bool not_prime[maxn];
LL Sum(LL x,LL y)
{
x %= mo; y %= mo;
LL R1 = ((1+x)*x>>1)%mo;
LL R2 = ((1+y)*y>>1)%mo;
return R1*R2%mo;
}
int main()
{
#ifdef DMC
freopen("table1.in","r",stdin);
#endif
k[1] = 1;
for (LL i = 2; i < maxn; i++) {
if (!not_prime[i]) {
k[i] = i*(1-i + mo) % mo;
prime[++tot] = i;
}
for (int j = 1; prime[j]*i < maxn; j++) {
not_prime[prime[j]*i] = 1;
if (i % prime[j] == 0) {
k[i*prime[j]] = 1LL*prime[j]*k[i]%mo;
break;
}
k[prime[j]*i] = k[prime[j]]*k[i]%mo;
}
}
for (LL i = 1; i < maxn; i++) k[i] = (k[i] + k[i-1]) % mo;
scanf("%lld%lld",&n,&m);
LL last,tail = min(n,m);
LL ans = 0;
for (LL i = 1; i <= tail; i = last + 1) {
last = min(n/(n/i),m/(m/i));
ans = (ans + Sum(n/i,m/i)*(k[last] - k[i-1] + mo)%mo)%mo;
}
printf("%lld",(ans + mo) % mo);
return 0;
}