GCD HDU

GCD

 HDU - 1695 

题意:给你5个数a,b,c,d,k。x属于[a,b]y属于[c,d]。 问你有多少对(x,y)的公约数为k。  注意(x,y)和 (y,x)视为同一对,a和c为1。

通过b/k,d/k,等价于把区间除以k,那么就变成了求有多少对(x,y)互素。

欧拉函数+容斥原理。

注意k可能为0.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=100010;
 5 vector<int> pri[maxn];
 6 int que[maxn];
 7 int phi[maxn];
 8 void get_phi(){
 9     memset(phi,0,sizeof(phi));
10     phi[1]=1;
11     for(int i=2;i<maxn;i++)if(!phi[i]){
12         for(int j=i;j<maxn;j+=i){
13             if(!phi[j]) phi[j]=j;
14             phi[j]=phi[j]/i*(i-1);
15         }
16     }
17    // for(int i=1;i<=20;i++) cout<<phi[i]<<endl;
18 }
19 void init(){
20     for(int i=2;i<maxn;i++){
21         pri[i].clear();
22         int temp=i;
23         for(int j=2;j*j<=i;j++) if(temp%j==0){
24             pri[i].push_back(j);
25             while(temp%j==0) temp/=j;
26         }
27         if(temp>1) pri[i].push_back(temp);
28     }
29 }
30 ll solve(int n,int s){
31     int cnt=0;
32     que[cnt++]=1;
33     for(int i=0;i<pri[s].size();i++){
34         int v=pri[s][i];
35         if(v>n) break;
36         int k=cnt;
37         for(int j=0;j<k;j++){
38             que[cnt++]=que[j]*v*(-1);
39         }
40     }
41     ll sum=0;
42     for(int i=0;i<cnt;i++) sum+=n/que[i];
43     return sum;
44 }
45 
46 int main(){
47     int t,kase=0;
48     get_phi();
49     init();
50     scanf("%d",&t);
51     while(t--){
52         printf("Case %d: ",++kase);
53         int a,b,c,d,k;
54         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
55         if(!k) {puts("0");continue;}
56         b/=k;d/=k;
57         if(b>d) swap(b,d);
58         ll ans=0;
59         for(int i=1;i<=b;i++) ans+=phi[i];
60         for(int i=b+1;i<=d;i++) ans+=solve(b,i);
61         printf("%lld
",ans);
62     }
63 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7401733.html