# 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  鲸头鹳  阅读(119)  评论(0编辑  收藏  举报