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 }