Noip 2009 Hankson 的趣味题

题目:给定正整数a0,a1,b0,b1,求出有多少个正整数x同时满足它和a0 的最大公约数是 a1,它和b0的最小公倍数是b1。对于 50%的数据,保证有 1≤a0,a1,b0,b1≤10000 且 n≤100。对于 100%的数据,保证有 1≤a0,a1,b0,b1≤2,000,000,000 且 n≤2000。

 

芒果君:直接暴力枚举有50分,这个x满足gcd(x,a0)=a1 && x*b0=gcd(x,b0)*b1

枚举的过程太长了就想想怎么优化。首先x一定是b1的倍数,那么k=b1/x也是b1的倍数,这样就把枚举的范围缩小到根号b1,每次都能判断两次,答案就出来了。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<iostream>
 5 #include<stack>
 6 #define inf 1<<29
 7 #define maxn 300010
 8 using namespace std;
 9 int a0,a1,b0,b1,ans,n;
10 int gcd(int x,int y){return y?gcd(y,x%y):x;}
11 inline bool check(int x){return (gcd(x,a0)==a1)&&(x*b0==gcd(x,b0)*b1);}
12 int main()
13 {
14     scanf("%d",&n);
15     while(n--){
16         scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
17         ans=0;
18         for(int i=1;i*i<=b1;++i){
19             if(b1%i==0){
20                 int k=b1/i;
21                 if(check(i)) ans++;
22                 if(i!=k) if(check(k)) ans++;
23             }
24         }
25         printf("%d\n",ans);
26     }
27     return 0;
28 }

 

posted @ 2017-10-31 22:32  五十岚芒果酱  阅读(148)  评论(0编辑  收藏  举报