0
点赞
收藏
分享

微信扫一扫

51nod 1479 小Y的数论题


1479 小Y的数论题
基准时间限制:1.5 秒 空间限制:131072 KB 分值: 640 难度:8级算法题 收藏 关注
小Y喜欢研究数论,并且喜欢提一些奇怪的问题。
这天他找了三个两两互质的数a, b, c,以及另一个数m, 现在他希望找到三个(0, m)范围内的整数x, y, z,使得
(xa+yb) Mod m=(zc) Mod m
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

【分析】
构造大法
令 x=2kb,y=2ka,z=2(kab+1)/c,那么原式就成立了233
所以我们要解出来k是啥…
不妨设 kab+1=cy,化简一下变成了cy−abk=1,用exgcd解出来y和k的正整数解就好了= =

题目有一个要求是说x,y,z>0,如果m是2的整数次幂,z搞不好mod m以后就变成0了…这时候就要加一个机智的特判…特判见代码,脑补一下。= =

【代码】

//51nod 1479 小Y的数论题
#include<bits/stdc++.h>
#define int long long
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
int n,m,a,b,c,x,y,k,T;
inline int ksm(int x,int k)
{
x%=m;
if(k==0) return 1;
if(k==1) return x;
int tmp=ksm(x,k>>1);
if(k&1) return tmp*tmp%m*x%m;
return tmp*tmp%m;
}
inline void exgcd(int a,int b,int &x,int &y)
{
if(!b) {x=1,y=0;return;}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
inline bool check(int n)
{
while(n%2==0) n/=2;
return n==1?1:0;
}
signed main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld%lld",&m,&a,&b,&c);
if(!check(m))
{
exgcd(c,a*b,y,x),k=-x;
while(k<0 || y<0) k+=c,y+=a*b;
printf("%lld %lld %lld\n",ksm(2,k*b),ksm(2,k*a),ksm(2,y));
}
else
{
if(a>1) printf("%lld 1 1\n",m/2);
else if(b>1) printf("1 %lld 1\n",m/2);
else if(c>1) printf("%lld %lld %lld\n",m/2,m/2,m/2);
else printf("1 1 2\n");
}
}
return 0;
}


举报

相关推荐

0 条评论