数学:莫比乌斯反演-约数个数和

BZOJ3994:利用莫比乌斯反演求约数个数和

解答此题需要利用约束个数函数的形式,将其与gcd联系再一起,然后再反演,推导

很麻烦

 1 #include<cstdio>
 2 #include<algorithm>
 3 using std::min;
 4 const int maxn=50005;
 5 int cnt;
 6 long long ans=0;
 7 bool vis[maxn];
 8 int mu[maxn],sum[maxn];
 9 long long prim[maxn],g[maxn];
10 inline long long read()
11 {
12     long long x=0,f=1;char ch=getchar();
13     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 void get_mu(int n)
18 {
19     mu[1]=1;
20     for(int i=2;i<=n;i++)
21     {
22         if(!vis[i]){prim[++cnt]=i;mu[i]=-1;}
23         for(int j=1;j<=cnt&&prim[j]*i<=n;j++)
24         {
25             vis[prim[j]*i]=1;
26             if(i%prim[j]==0) break;
27             else mu[i*prim[j]]=-mu[i];
28         }
29     }
30     for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
31     for(int i=1;i<=n;i++)
32     {
33         for(int l=1,r;l<=i;l=r+1)
34         {
35             r=(i/(i/l));
36             g[i]+=(long long)(r-l+1)*(long long)(i/l);
37         }
38     }
39 }
40 int main()
41 {
42     int T,n,m,max_rep;
43     T=read();
44     get_mu(50000);
45     while(T--)
46     {
47         ans=0;
48         n=read();m=read();
49         max_rep=min(n,m);
50         for(int l=1,r;l<=max_rep;l=r+1)
51         {
52             r=min(n/(n/l),m/(m/l));
53             ans+=(sum[r]-sum[l-1])*(long long)g[n/l]*(long long)g[m/l];
54         }
55         printf("%lld\n",ans);
56     }
57     return 0;
58 }

 

posted @ 2018-09-25 19:10  静听风吟。  阅读(204)  评论(0编辑  收藏  举报