您的位置:首页 > 其它

数学-洛谷P1072 Hankson 的趣味题

2017-03-31 20:02 281 查看
https://daniu.luogu.org/problem/show?pid=1072

一开始想了一个暴力,感觉很好;

我们考虑lcm;

lcm(a,b)=a*b/gcd(a,b);

这个因为两个互质的数lcm是其乘积可得;

显然我们读入一个b,要求a;

那么a一定被lcm整除;

而且枚举a直接枚举sqrt(lcm)就可以了;

所以时间复杂度将近1e5*O(gcd);

但这样是过不掉的;

各种瞎优化;

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define Ll long long
using namespace std;
int x,y,X,Y,m,ans,n;
int gcd(int x,int y){//非递归迭代加深gcd
int temp=1,X,Y; //本以为会很快,结果好像一般般
while(1){
if(x<y)swap(x,y);
if(!y)return x*temp;
if(x&1)
if(y&1)X=y,Y=x-y;
else   X=y/2,Y=x;
else
if(y&1)X=x/2,Y=y;
else   X=x/2,Y=y/2,temp*=2;
x=X; y=Y;
}
}
int main()
{
scanf("%d",&m);
while(m--){
ans=0;
scanf("%d%d%d%d",&x,&y,&X,&Y);
int A=x/y,B=Y/X,C=sqrt(Y);//这个一定要放在外面
for(int i=1;i<=C;i++)
{
if(Y%i)continue;//这样写我们就可以直接用int了
if(i%y==0)if(gcd(A,i/y)==1)if(gcd(B,Y/i)==1)ans++;
n=Y/i;
if(n==i)continue;//为什么这样可以写
if(n%y==0)if(gcd(A,n/y)==1)if(gcd(B,Y/n)==1)ans++;
}//和gcd,lcm的定义及基本数学质知识有关
printf("%d\n",ans);
}
}


小证明(从洛谷题解里面抄的)

lcm(x,b0)=x*b0/gcd(x,b0)=b1

=> b1*gcd(x,b0)=x*b0

=> gcd(x,b0)=x*b0/b1

=> gcd(b1/b0,b1/x)=1

标算

设x=a1*a2;a0=a1*a3;x*b2=b1;b0*b3=b1;

则a1*a2*b2=b1

又a1是x和a0的最大公约数,所以a2和a3互质。

又b1是x和b0的最小公倍数,所以b2和b3互质。

所以a2和a0/a1,b2和b1/b0互质。

因为a1*a2*b2=b1

所以a2*b2=b1/a1

因此a2,b2是b1/a1的因子,只需枚举并且判断是否与a3,b3互质即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: