51nod 1479 小Y的数论题

来源:互联网 发布:电脑找不到windows 编辑:程序博客网 时间:2024/05/19 06:38

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=2kby=2kaz=2(kab+1)/c,那么原式就成立了233
所以我们要解出来k是啥…
不妨设 kab+1=cy,化简一下变成了cyabk=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;}