码迷,mamicode.com
首页 > 其他好文 > 详细

【莫比乌斯反演】BZOJ2820 YY的GCD

时间:2015-06-24 14:19:38      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:

Description

  求有多少对(x,y)的gcd为素数,x<=n,y<=m。n,m<=1e7,T<=1e4。

 

Solution

  因为题目要求gcd为素数的,那么我们就只考虑素数mu的贡献就行了

  对于p,对于k*p的贡献是mu[k]

  然后加上整除分块优化就行了

  p可以筛完素数处理,处理复杂度为O(n/log*log)正好为O(n)

 

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 
 7 const int maxn=1e7+5;
 8 
 9 int flag[maxn],prime[maxn],mu[maxn],cnt;
10 ll sum[maxn];
11 int n,m;
12 
13 void getmu(){
14     mu[1]=1;
15     for(int i=2;i<=1e7;i++){
16         if(!flag[i]){
17             prime[++cnt]=i;
18             mu[i]=-1;
19         }
20         for(int j=1;i*prime[j]<=1e7&&j<=cnt;j++){
21             flag[i*prime[j]]=1;
22             if(i%prime[j]==0){
23                 mu[i*prime[j]]=0;
24                 break;
25             }
26             mu[i*prime[j]]=-mu[i];
27         }
28     }
29     for(int i=1;i<=cnt;i++)
30         for(int j=prime[i];j<=1e7;j+=prime[i])
31             sum[j]+=mu[j/prime[i]];
32     for(int i=1;i<=1e7;i++)
33         sum[i]+=sum[i-1];
34 }
35 
36 int main(){
37     getmu();
38     int T;
39     scanf("%d",&T);
40     while(T--){
41         scanf("%d%d",&n,&m);
42         if(n>m) swap(n,m);
43         ll ans=0;
44         for(int i=1,pos=1;i<=n;i=pos+1){
45             pos=min(n/(n/i),m/(m/i));
46             ans+=(sum[pos]-sum[i-1])*(n/i)*(m/i);
47         }
48         printf("%lld\n",ans);
49     }
50     return 0;
51 }

 

【莫比乌斯反演】BZOJ2820 YY的GCD

标签:

原文地址:http://www.cnblogs.com/xkui/p/4597432.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!