Soulation to NOI Online T2数学游戏
题目描述
输入格式
第一行一个整数 ,表示有 t 对正整数 x 和 z。
接下来 t 行,每行两个正整数 x 和 z,含义见题目描述。
输出格式
对于每对数字输出一行,如果不存在满足条件的正整数 y,请输出 ?1,否则输出满足条件的最小正整数 y。
数据范围
样例 输入
1
10 240
输出
12
算法:
数学推导
预备知识(大佬略)
- gcd
正片
一.考场代码
- 易知 若gcd(x,y)=d,则x=q*d,y=p*d,且(p,q)=1,所以z=q*d*p*d*d
- 那么,我发现p*d*d=y*d=z/x,所以d2一定是z/x的约数,所以只要从1~√z/x
- 如果枚举的d是x的约数,且(q,p)=1,则输出
二.正解
其实就一行话
如果(p,q)=1,则(p2,q)=1,又因x2=(p2*d2),z/x=(q*d2)
所以d2=gcd(p2*d2,q*d2)
注意:要开long long,还要判z%x==0
C++代码
水过70分
1 #include2 using namespace std; 3 typedef unsigned long long ull; 4 int t; 5 ull gcd(ull a,ull b) 6 { 7 if(b==0)return a; 8 return gcd(b,a%b); 9 } 10 int main() 11 { 12 // freopen("math.in","r",stdin); 13 // freopen("math.out","w",stdout); 14 cin>>t; 15 while(t--) 16 { 17 ull x,z; 18 scanf("%llu%llu",&x,&z); 19 if(z%x!=0) 20 { 21 puts("-1"); 22 continue; 23 } 24 if(z==x) 25 { 26 puts("1"); 27 continue; 28 } 29 ull d=z/x; 30 ull a=sqrt(z/x)+1; 31 bool flag=false; 32 for(ull i=1;i<=a;i++) 33 { 34 if(d%(i*i)==0) 35 { 36 ull n=d/i/i; 37 if(x%i!=0)continue; 38 ull m=x/i; 39 if(gcd(n,m)==1) 40 { 41 // cout< 42 printf("%llu\n",n*i); 43 flag=true; 44 break; 45 } 46 } 47 } 48 if(!flag)puts("-1"); 49 } 50 return 0; 51 } 52 /* 53 3 54 5 30 55 4 8 56 11 11 57 */
100分
1 #include2 using namespace std; 3 typedef long long ll; 4 ll gcd(ll x,ll y) 5 { 6 if(y==0)return x; 7 return gcd(y,x%y); 8 } 9 int main() 10 { 11 int t; 12 cin>>t; 13 while(t--) 14 { 15 ll x,z; 16 cin>>x>>z; 17 ll d=gcd(x*x,z/x); 18 ll t=sqrt(d); 19 if(z%x!=0)puts("-1"); 20 else if(t*t!=d)puts("-1"); 21 else if(z%(x*t)==0)cout< endl; 22 else puts("-1"); 23 } 24 return 0; 25 }