BZOJ 2154/2693 Crash的数字表格/jzptab (莫比乌斯反演)

题目大意:求$\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)$的和

易得$\sum_{i=1}^{n}\sum_{j=1}^{m}\frac{ij}{gcd(i,j)}$

套路1:提取出$gcd$

$\sum_{k=1}^{n}\frac{1}{k}\sum_{i=1}^{n}\sum_{j=1}^{m}ij[gcd(i,j)==k]$

$\sum_{k=1}^{n}k\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}ij[gcd(i,j)==1]$

$\sum_{k=1}^{n}k\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}ij\sum_{d|gcd(i,j)}\mu(d)$

套路2:继续提取$gcd$

$\sum_{k=1}^{n}k\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}[gcd(i,j)==d]ij$

$\sum_{k=1}^{n}k\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}d^{2}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{kd} \right \rfloor}ij$

$\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{kd} \right \rfloor}ij$可以$O(1)$计算出来

套路3:令$Q=kd$

$\sum_{Q=1}^{n}\sum_{i=1}^{\left \lfloor \frac{n}{Q} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{Q} \right \rfloor}ij\sum_{d|Q}\frac{Q}{d}(d)^{2}\mu(d)$

$\sum_{d|Q}\frac{Q}{d}(d)^{2}\mu(d)$显然是积性函数

然后问题就解决了

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define N 10010000
 5 #define maxn 10000000
 6 #define ll long long 
 7 #define uint unsigned int
 8 #define rint register int
 9 using namespace std;
10 
11 int n,m,T,cnt;
12 int mu[N],pr[N],use[N];
13 int f[N],F[N];
14 const int mod=100000009;
15 
16 void Pre()
17 {
18     mu[1]=1;f[1]=1;
19     for(int i=2;i<=maxn;i++)
20     {
21         if(!use[i]) pr[++cnt]=i,mu[i]=-1,f[i]=(1ll*i*(1-i))%mod;
22         for(rint j=1;j<=cnt&&i*pr[j]<=maxn;j++){
23             use[i*pr[j]]=1;
24             if(i%pr[j]){
25                 mu[i*pr[j]]=-mu[i];
26                 f[i*pr[j]]=1ll*f[i]*f[pr[j]]%mod;
27             }else{
28                 mu[i*pr[j]]=0;
29                 f[i*pr[j]]=1ll*f[i]*pr[j]%mod;
30                 break;
31             }
32         }
33     }
34     for(int i=1;i-4<=maxn;i+=4)
35     {
36         F[i+0]=(1ll*F[i-1]+f[i+0])%mod;
37         F[i+1]=(1ll*F[i+0]+f[i+1])%mod;
38         F[i+2]=(1ll*F[i+1]+f[i+2])%mod;
39         F[i+3]=(1ll*F[i+2]+f[i+3])%mod;
40     }
41 }
42 ll solve(int n,int m)
43 {
44     ll ans=0,sn,sm;
45     if(n>m) swap(n,m);
46     for(int i=1,la;i<=n;i=la+1)
47     {
48         la=min(n/(n/i),m/(m/i));
49         sn=(1ll*(n/i)*(n/i+1)/2)%mod;
50         sm=(1ll*(m/i)*(m/i+1)/2)%mod;
51         (ans+=1ll*sn*sm%mod*(F[la]-F[i-1]))%=mod;
52     }ans=(ans%mod+mod)%mod;
53     return ans;
54 }
55 
56 int main()
57 {
58     //freopen("t1.in","r",stdin);
59     scanf("%d",&T);
60     Pre();
61     int n,m;
62     while(T--)
63     {
64         scanf("%d%d",&n,&m);
65         printf("%lld\n",solve(n,m));
66     }
67     return 0;
68 }

调试部分的代码..留个纪念吧

 1 int ps[N],son[N],d[N],num,nson;
 2 void dfs_son(int s,int dep)
 3 {
 4     if(dep>num) {son[++nson]=s;return;}
 5     for(int j=0;j<=d[dep];j++)
 6         dfs_son(s,dep+1),s*=ps[dep];
 7 }
 8 ll g[N];
 9 void check()
10 {
11     for(int i=1;i<=maxn;i++){
12         int sq=sqrt(i),x=i;
13         num=nson=0;
14         for(int j=1;j<=cnt&&pr[j]<=sq;j++)
15             if(x%pr[j]==0){
16                 ps[++num]=pr[j];
17                 while(x%pr[j]==0) d[num]++,x/=pr[j];
18             }
19         if(x!=1) ps[++num]=x,d[num]=1;
20         dfs_son(1,1);
21         for(int j=1;j<=nson;j++)
22             (g[i]+=mu[son[j]]*son[j]%mod)%=mod,
23             son[j]=0;
24         g[i]=g[i]*i%mod;
25         for(int i=1;i<=num;i++) 
26             d[i]=0;
27     }
28 }

 

posted @ 2018-11-18 22:32  guapisolo  阅读(205)  评论(0编辑  收藏  举报