[bzoj2154]Crash的数字表格(mobius反演)

题意:$sumlimits_{i = 1}^n {sumlimits_{j = 1}^m {lcm(i,j)} } $

解题关键:

$sumlimits_{i = 1}^n {sumlimits_{j = 1}^m {lcm(i,j)} }  = sumlimits_{i = 1}^n {sumlimits_{j = 1}^m {frac{{i*j}}{{gcd (i,j)}}} } $

枚举gcd,上式化为:

$sumlimits_{d = 1}^{min (n,m)} {dsumlimits_{egin{array}{*{20}{c}}
{gcd (i,j) = = 1}\
{1 < = i < = n/d}\
{1 < = j < = m/d}
end{array}} {i*j} } $

$f(n,m,k) = sumlimits_{egin{array}{*{20}{c}}
{gcd (i,j) = = k}\
{1 < = i < = n}\
{1 < = j < = m}
end{array}} {i*j} $

由于

$sum(n,m) = sumlimits_{egin{array}{*{20}{c}}
{1 < = i < = n}\
{1 < = j < = m}
end{array}} {i*j} = frac{{n(n + 1)}}{2}frac{{m(m + 1)}}{2}$

$egin{array}{l}
F(n,m,k) = sumlimits_{k|d} {f(n,m,d) = sumlimits_{egin{array}{*{20}{c}}
{1 < = i < = n}\
{1 < = j < = m}\
{k|gcd (i,j)}
end{array}} {i*j} = {k^2}sum(leftlfloor {frac{n}{k}} ight floor ,leftlfloor {frac{m}{k}} ight floor )} \
f(n,m,k) = sumlimits_{k|d} {u(frac{d}{k})F(n,m,d)}
end{array}$

而此题中,$k==1$,

则,

$egin{array}{l}
f(n,m,1) = sumlimits_{d = 1}^{min (n,m)} {u(d)F(n,m,d)} \
= sumlimits_{d = 1}^{min (n,m)} {u(d){d^2}sum(leftlfloor {frac{n}{d}} ight floor ,leftlfloor {frac{m}{d}} ight floor )} \
ans = sumlimits_{d = 1}^{min (n,m)} {d*f(leftlfloor {frac{n}{d}} ight floor ,leftlfloor {frac{m}{d}} ight floor ,1)}
end{array}$

 求解ans和$f$函数复杂度都是$O(sqrt n )$,所以最终复杂度为$O(n)$。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<iostream>
 7 #define Sum(x,y) (x*(x+1)/2%mod*(y*(y+1)/2%mod)%mod)
 8 using namespace std;
 9 typedef long long ll;
10 const ll mod=20101009;
11 const ll maxn=10000000+200;
12 ll n,m;
13 bool vis[maxn];
14 ll prime[maxn],mu[maxn],sum1[maxn];
15 void init_mu(ll n){
16     ll cnt=0;
17     mu[1]=1;
18     for(ll i=2;i<n;i++){
19         if(!vis[i]){
20             prime[cnt++]=i;
21             mu[i]=-1;
22         }
23         for(ll j=0;j<cnt&&i*prime[j]<n;j++){
24             vis[i*prime[j]]=1;
25             if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
26             else { mu[i*prime[j]]=-mu[i];}
27         }
28     }
29     sum1[0]=0;
30     for(ll i=1;i<n;i++) sum1[i]=(sum1[i-1]+1ll*mu[i]*i*i)%mod;
31 }
32 ll calf(ll n,ll m){
33     ll ans=0,pos,len=min(n,m);
34     for(ll i=1;i<=len;i=pos+1){
35         pos=min(n/(n/i),m/(m/i));
36         //ans+=(sum1[pos]-sum1[i-1])%mod*((n/i)*((n/i)+1)/2%mod*(((m/i)+1)*(m/i)/2%mod)%mod);
37         ans+=(sum1[pos]-sum1[i-1])%mod*Sum(n/i,m/i)%mod;//最好用函数写出 
38         ans%=mod;
39         
40     }
41     return ans;
42 }
43 ll calres(ll n,ll m){
44     ll ans=0,pos,len=min(n,m);
45     for(ll i=1;i<=len;i=pos+1){
46         pos=min(n/(n/i),m/(m/i));
47         ans+=(i+pos)*(pos-i+1)/2%mod*calf(n/i,m/i)%mod;
48         ans%=mod;
49     }
50     return (ans%mod+mod)%mod;
51 }
52 
53 int main(){
54     scanf("%lld%lld",&n,&m);
55     init_mu(min(n,m)+10);
56     printf("%lld
",calres(n,m));
57     return 0;
58 }