BZOJ 3994: [SDOI2015]约数个数和3994: [SDOI2015]约数个数和 莫比乌斯反演

https://www.lydsy.com/JudgeOnline/problem.php?id=3994

https://blog.csdn.net/qq_36808030/article/details/77056706

莫比乌斯反演,我现在莫比乌斯反演都不会写不会推了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 #define LL long long
 9 const int maxn=50010;
10 int mu[maxn]={},pri[maxn]={},tot=0;
11 bool v[maxn]={};LL f[maxn]={};
12 void get_mu(int n){
13     mu[1]=1;
14     for(int i=2;i<=n;++i){
15         if(!v[i]){pri[++tot]=i;mu[i]=-1;}
16         for(int j=1;j<=tot&&pri[j]*i<=n;++j){
17             int w=pri[j]*i;v[w]=1;
18             if(i%pri[j]==0){mu[w]=0;break;}
19             mu[w]=mu[i]*(-1);
20         }
21     }
22     for(int i=1;i<=n;++i){
23         mu[i]+=mu[i-1];
24         for(int j=1,las;j<=i;j=las+1){
25             las=i/(i/j);
26             f[i]+=(LL)(las-j+1)*(LL)(i/j);
27         }
28     }
29 }
30 int main(){
31     get_mu(maxn-10);
32     int T;scanf("%d\n",&T);
33     while(T-->0){
34         int n,m; scanf("%d%d",&n,&m);
35         if(n>m)swap(n,m);
36         LL ans=0;
37         for(int i=1,las;i<=n;i=las+1){
38             las=min(n/(n/i),m/(m/i));
39             ans+=(LL)(mu[las]-mu[i-1])*f[n/i]*f[m/i];
40         }
41         printf("%lld\n",ans);
42     }
43     return 0;
44 }
View Code

 

posted @ 2018-06-27 22:10  鲸头鹳  阅读(137)  评论(0编辑  收藏  举报