小Y喜欢研究数论,并且喜欢提一些奇怪的问题。
这天他找了三个两两互质的数a, b, c,以及另一个数m, 现在他希望找到三个(0, m)范围内的整数x, y, z,使得
(xa+y
Input
第一行一个数代表数据组数T 接下来T行每行四个整数m, a, b, c 满足a, b, c两两互质 1 <= T <= 100000 1 <= a, b, c <= 10^9 3 <= m <= 10^9
Output
对于每组数据,如果不存在x, y, z满足条件,则输出"Stupid xiaoy"(不含引号) 否则输出一行三个数分别为x, y, z
Input示例
1 100 1 1 1
Output示例
1 2 3
思路:
考虑构造形如2^kab+2^kab=2^(kab+1)的式子
那么只要找到合理的k使得(kab + 1)能被c整除,就可以构造出满足条件的x y z
设
kab+1=lc
那么有
lc−kab=1
可以用扩展欧几里得解这个不定方程
此时存在的唯一问题是,若m是2的次幂,那么取模之后结果可能是0
这种情况可以特殊处理,例如:
若a > 1,取x = m / 2, y = z = 1
b > 1类似
否则若c > 1, 取x = y = z = m / 2
否则取x = y = 1, z = 2
1 #include <stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<iostream> 7 using namespace std; 8 typedef long long LL; 9 pair<LL,LL>exgcd(LL n,LL m); 10 LL quick(LL n,LL m,LL mod); 11 int main(void) 12 { 13 LL m,a,b,c; 14 LL x,y,z; 15 int T; 16 scanf("%d",&T); 17 while(T--) 18 {scanf("%lld %lld %lld %lld",&m,&a,&b,&c); 19 if(m&(m-1)) 20 { 21 pair<LL,LL>ask = exgcd(c,a*b); 22 ask.second = -ask.second; 23 while(ask.first<0||ask.second<0) 24 { 25 ask.first+=a*b; 26 ask.second+=c; 27 } 28 x = quick((LL)2,ask.second*b,m); 29 y = quick((LL)2,ask.second*a,m); 30 z = quick((LL)2,ask.first,m); 31 } 32 else 33 { //printf("1 "); 34 if(a > 1) 35 { 36 x = m/2; 37 y = 1; 38 z = 1; 39 } 40 else if(b>1) 41 { 42 x = 1; 43 y = m/2; 44 z = 1; 45 } 46 else if(c > 1) 47 { 48 x = m/2; 49 y = m/2; 50 z = m/2; 51 } 52 else 53 { 54 x = 1; 55 y = 1; 56 z = 2; 57 } 58 } 59 printf("%lld %lld %lld ",x,y,z);} 60 return 0; 61 } 62 pair<LL,LL>exgcd(LL n,LL m) 63 { 64 if(m==0) 65 return make_pair(1,0); 66 else 67 { 68 pair<LL,LL>ak = exgcd(m,n%m); 69 return make_pair(ak.second,ak.first-(n/m)*ak.second); 70 } 71 } 72 LL quick(LL n,LL m,LL mod) 73 { 74 LL ask = 1; 75 while(m) 76 { 77 if(m&1) 78 ask = ask*n%mod; 79 n = n*n%mod; 80 m/=2; 81 } 82 return ask; 83 }