#include <iostream> #include<cstdio> using namespace std; void extend_Eu(int a,int b,int &f,int &x,int &y){ if(b==0){ x=1; y=1; f=a; return ; } extend_Eu(b,a%b,f,x,y); int t=x; x=y; y=t-a/b*y; } int main() { //freopen("cin.txt","r",stdin); int T,a,m; while(cin>>T){ while(T--){ int b,f,x,y; scanf("%d%d",&a,&m); b=m; extend_Eu(a,b,f,x,y); if(f!=1){ cout<<"Not Exist\n"; continue; } //if(gcd(a,x)!=1) while(x<0){ x+=b; } cout<<x<<endl; } } return 0; }
import java.util.*; public class Main { static long gcd(long a,long b){ return b!=0?gcd(b,a%b):a; } static long Extend_Eulid(long d,long f) { long x1=1,x2=0,x3=f,y1=0,y2=1,y3=d ; while(y3>0 && y3!=1) { long q=x3/y3 ; long t1,t2,t3 ; t1=x1-q*y1; t2=x2-q*y2; t3=x3-q*y3; x1=y1; x2=y2; x3=y3 ; y1=t1; y2=t2; y3=t3 ; } if(y3==0)return -1 ; return y2 ; } public static void main(String[] args) { long t,n,d,x,y; Scanner sc=new Scanner (System.in); t=sc.nextLong(); for(int i=0;i<t;i++){ n=sc.nextLong(); d=sc.nextLong(); x=sc.nextLong(); y=sc.nextLong(); long c=(y-x+n)%n; long gd=gcd(d,n); if(c%gd!=0){ System.out.println("Impossible"); continue; } d/=gd; n/=gd; long res=Extend_Eulid(d,n); if(res<0) res+=n; res=res*(c/gd)%n; System.out.println(res); } } }
中国古代求解一次同余式组的方法:
数学著作《孙子算经》卷下第二十六题,叫做“物不知数”问题,原文如下:有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
即:已知 n%3=2, n%5=3, n%7=2, 求n。 (假设除数两两互质)那么n =(70×x+21×y+15×z)%lcm(3,5,7) = 23 这是n的最小解。
用程序实现:
#include <iostream> #include<cstdio> using namespace std; int gcd(int a,int b){ return b?gcd(b,a%b):a; } int get(int a,int b,int c){ int lc=a*b/gcd(a,b),ans=lc; while(ans%c!=1){ ans+=lc; } return ans; } int main() { int m[3]={3,5,7},n[3]={2,3,2}; //m,n分别代表除数和余数 //int m[3]={23,28,33},n[3]={283,102,23}; int r=gcd(gcd(m[0],m[1]),m[2]),D=m[0]*m[1]*m[2]/r; int q1=get(m[1],m[2],m[0]),q2=get(m[0],m[2],m[1]),q3=get(m[0],m[1],m[2]); printf("%d\n",(q1*n[0]+q2*n[1]+q3*n[2])%D); return 0; }
#include <iostream> #include<cstdio> using namespace std; int get(int a,int b,int c){ int lc=a*b,ans=lc; while(ans%c!=1){ ans+=lc; } return ans; } int main() { //freopen("cin.txt","r",stdin); int p,e,i,d,k=0; // 23, 28, and 33 int pd=get(28,33,23),ed=get(23,33,28),id=get(23,28,33); while(~scanf("%d%d%d%d",&p,&e,&i,&d)){ if(p==-1)break; int ans=(pd*p+ed*e+id*i)%21252; ans=(ans-d+21252)%21252; //防止负数的产生。 if(ans==0)ans+=21252; //防止得出的结果和题目给出的日期一样。 printf("Case %d: the next triple peak occurs in %d days.\n",++k,ans); } return 0; }