NOIP2009 HankSon的趣味题

  这又是一道省选的数学题,由于本蒟蒻数学很烂,在此不给出详细的证明过程,只是简述下目标和结论;

  如果我们想证的话,可以证明出:

  如果gcd(x,a0)=a1,那么gcd(x/a1,a0/a1) (可以往最大公约数的性质方面考虑,如果除出来的数还不互质,证明原数一定不是最大公约数)

  此外:这里引用学长证明

  然后发现,b1一定是x的整倍数,而x一定是a1的整倍数,所以可以采取枚举b1的因子;

上代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<string>
 7 #include<algorithm>
 8 #include<queue>
 9 #include<bitset>
10 #include<set>
11 using namespace std;
12 int gcd(int a,int b){return b==0 ? a:gcd(b,a%b);}//辗转相除法 
13 int main()
14 {
15     int T;
16     scanf("%d",&T);
17     while(T--){
18         int a0,a1,b0,b1;
19         scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
20         int p=b1/b0,q=a0/a1,ans=0;
21         for(int x=1;x*x<=b1;x++){
22             if(b1%x!=0) continue;//枚举到的必须是b1的因子 
23             if(x%a1==0&&gcd(q,x/a1)==1&&gcd(p,b1/x)==1) ans++;
24             int y=b1/x;//找到第二个因子,借此来简化计算 
25             if(x==y) continue;//找重了排除掉 
26             if(y%a1==0&&gcd(q,y/a1)==1&&gcd(p,b1/y)==1) ans++;
27         }
28         cout<<ans<<endl;
29     }
30     return 0;
31 }
View Code

 

posted @ 2018-05-02 21:14  杜宇一声  阅读(173)  评论(0编辑  收藏  举报