题目描述
小Y喜欢研究数论,并且喜欢提一些奇怪的问题。
这天他找了三个两两互质的数a, b, c,以及另一个数m, 现在他希望找到三个(0, m)范围内的整数x, y, z,使得
(x^a+y^b) Mod m=(z^c) Mod m
构造
我们知道2^x+2^x=2^(x+1)
于是我们这样构造:
若m不为2的幂数,我们令x=2^kb,y=2^ka,z=2^l,那么cl-kab=1,可以用扩展欧几里得求解。
否则,更容易构造,讨论a、b、c是否大于1,然后均为1也容易构造,详见代码。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll a,b,c,x,y,z,m,l,k,xx,yy,t,ca;
void gcd(ll a,ll b){
if (!b){
xx=1;
yy=0;
return;
}
else{
ll x,y;
gcd(b,a%b);
x=yy;
y=xx-(a/b)*yy;
xx=x;yy=y;
}
}
ll quicksortmi(ll x,ll y,ll mo){
if (!y) return 1;
ll t=quicksortmi(x,y/2,mo);
t=t*t%mo;
if (y%2) t=t*x%mo;
return t;
}
int main(){
scanf("%lld",&ca);
while (ca--){
scanf("%lld%lld%lld%lld",&m,&a,&b,&c);
t=m;
while (t%2==0) t/=2;
if (t==1){
if (a>1){
x=m/2;
y=z=1;
}
else if (b>1){
y=m/2;
x=z=1;
}
else if (c>1) x=y=z=m/2;
else{
x=y=1;
z=2;
}
}
else{
gcd(c,a*b);
l=xx;k=yy;
while (l<0||k>0){
l+=a*b;
k-=c;
}
z=quicksortmi(2,l,m);
x=quicksortmi(2,k*b,m);
y=quicksortmi(2,k*a,m);
}
printf("%lld %lld %lld\n",x,y,z);
}
}