NOIP2009 Hankson的趣味题(还真是有趣呢!)
2018-04-01 21:38
393 查看
这道题最开始的想法就没想得到100分,看到这么大的范围就知道一定有规律可循,但是对于一个我这样的数学渣来说,满分早就离我而去了,那么就来看下50分怎么去解决。首先我们可以算出的是两个数的GCD,
那么我们只需要列举a1的倍数,然后判断最大公约数是不是a1就可以了,然后并将之标记,然后再在1~b1的范围内查找到x符合x和b0的最小公倍数是b1,然后也标记,那么可以知道,当两个都标记了的时候,就++ans,然后最后输出就行了,下面是代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #pragma G++ optamize (2) using namespace std; long long a0,a1,b0,b1; long long gcd(long long a,long long b) { if(b==0) return a; else return gcd(b,a%b); } int idx1=0,idx2=0; long long maxx=-1; vector<long long>a; vector<long long>b; int main() { int n; cin>>n; while(n--) { while(a.size()) { a.pop_back(); } while(b.size()) { b.pop_back(); } cin>>a0>>a1>>b0>>b1; maxx=max(maxx,a0); maxx=max(maxx,a1); maxx=max(maxx,b0); maxx=max(maxx,b1); for(long long i=1; i<=maxx; i++) if(gcd(i,a0)==a1) a.push_back(i); for(long long i=1; i<=maxx; i++) { long long k=gcd(i,b0); if(b1==i*b0/k) b.push_back(i); } int tot=0; for(int i=0; i<a.size(); i++) { for(int j=0; j<b.size(); j++) { if(a[i]==b[j]) tot++; } } cout<<tot<<endl; } }
那么正解是怎样的呢?这就要用到一个神奇的方法:
对于两个正整数a,b,设 gcd(a,b)=k,则存在gcd(a/k,b/k)=1 gcd(b1/b0,b1/x)=1 用心体会这两个式子,发现x是a1的整数倍且是b1的因子 b√1枚举b1的因子(也就是x),如果这个数是a1的整数倍,并且满足那两个式子,ans++ gcd(x/a1,a0/a1)=1; gcd(b1/b0,b1/x)=1;
那就是这样,在经过一系列修改,下面是最终代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<algorithm> #define inf 1000000000 #define N 50000 #define ll long long using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,tot; int a0,b0,a1,b1,ans; int pri[50005]; bool mark[50005]; void getpri() { for(int i=2;i<=N;i++) { if(!mark[i])pri[++tot]=i; for(int j=1;j<=tot&&pri[j]*i<=N;j++) { mark[pri[j]*i]=1; if(pri[j]%i==0)break; } } } void solve(int x) { int c0=0,c1=0,c2=0,c3=0; while(a0%x==0){a0/=x;c0++;} while(a1%x==0){a1/=x;c1++;} while(b0%x==0){b0/=x;c2++;} while(b1%x==0){b1/=x;c3++;} if(c0==c1&&c2==c3) { if(c1<=c3)ans*=c3-c1+1; else ans=0; } else if(c0!=c1&&c2!=c3&&c1!=c3)ans=0; } int main() { getpri(); n=read(); while(n--) { ans=1; a0=read();a1=read();b0=read();b1=read(); for(int i=1;i<=tot;i++) solve(pri[i]); if(b1!=1)solve(b1); printf("%d\n",ans); } return 0; }
相关文章推荐
- 小Y的数学作业(Hankson 的趣味题)[NOIP2009提高组][Codevs1172]
- Hankson的趣味题[NOIP2009]解题报告
- NOIP2009 Hankson的趣味题
- 洛谷 P1072 [NOIP2009 T2] Hankson 的趣味题
- [NOIP 2009提高] Hankson的趣味题
- NOIP2009 题解 潜伏者 Hankson的趣味题 最优贸易 靶形数独
- 数学——Luogu1072 [NOIP2009]Hankson 的趣味题
- [jzoj2538]【NOIP2009TG】Hankson 的趣味题
- NOIp2009 Hankson的趣味题
- noip2009 Hankson的趣味题
- NOIP2009 Hankson的趣味题 [数论]
- NOIP2009 Hankson的趣味题
- noip2009 luogu1072 Hankson的趣味题
- Noip 2009 解题报告(潜伏着,Hankson的趣味题,最优贸易,靶形数独)
- 【数论】noip2009Hankson 的趣味题
- 【NOIP 2009 提高组】Hankson 的趣味题
- NOIP2009 潜伏者 Hankson的趣味题 最优贸易 靶形数独
- 【NOIP 2009】Hankson的趣味题 分析&渣程序(增补对于大质数的分析)
- 【NOIP2009】Hankson的趣味题 数论题,质因数分解处理
- 【NOIP2009】Hankson 的趣味题