擴充套件歐幾里得,線性同餘方程 poj1845
阿新 • • 發佈:2019-01-08
定理:對於任意整數a,b存在一堆整數x,y,滿足ax+by=gcd(a,b)
int exgcd(int a,int b,int &x,int &y){ if(b==0){x=1,y=0;return a;} int d=exgcd(b,a%b,x,y); int z=x;x=y;x=z-y*(a/b); return d; }
當d可以整除c時,一般方程ax+by=c的一組特解求法:
1.求ax+by=d的特解x0,y0
2.ax+by=c的特解為(c/d)x0,(c/d)y0
上述方程的通解:(c/d)x0+k(b/d) ,(c/d)y0-k(a/d)
乘法逆元:b,m互質,並且b整除a,則存在x,有a/b = a*x(mod m),即a/b模m的結果和a*x模m的結果是相同的,這個x稱為b的模m的乘法逆元,記作b^(-1) (mod m)
可得b*b^(-1) = 1(mod m)
那麼當m是質數時,根據費馬小定理,有b^(m-1)=1(mod m),那麼b的逆元就是b^(m-2)
如果只是保證b,m互質,那麼解同餘方程b*x=1(mod m)可以求出x
所以當遇到除法取模運算時,可以先求出逆元,轉換成乘法取模運算
/* 如果單獨是個A,那麼就可以分解質因數後用公式求約數個數 那麼B個A相乘,其約數個數就是mul{1+p^1+p^2...+p^B*ci} 結果是比數列求和後再相乘,每項等比數列的結果是 (pi^(B*ci+1)-1)/(pi-1) mod9901, 1.pi-1不是9901的倍數,(pi-1)^(9901-2)就是逆元 2.pi-1是9901的倍數,逆元不存在,但是pi mod 9901=1。。。 先把A分解質因數,再等比數列求和(快速冪+逆元),*/ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define ll long long #define mod 9901 int m,p[200],c[200]; void divide(int n){ m=0; for(int i=2;i*i<=n;i++) if(n%i==0){ p[++m]=i,c[m]=0; while(n%i==0) n/=i,c[m]++; } if(n>1) p[++m]=n,c[m]=1; } ll pow(ll a,ll b){ ll res=1; while(b){ if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; } return res; } int main(){ ll a,b,ans=1; scanf("%lld%lld",&a,&b); divide(a);//分解質因數 for(int i=1;i<=m;i++){ if((p[i]-1)%mod==0){ ans=ans*(b*c[i]+1)%mod; continue; } //求分子和分母逆元 ll x=pow(p[i],b*c[i]+1)%mod; x=(x-1+mod)%mod; ll y=pow(p[i]-1,mod-2)%mod; ans=ans*x%mod*y%mod; } printf("%lld\n",ans); }
求解同餘方程:a*x=b(mod m)等價於a*x-b是m的倍數,等價於a*x+m*y=b,當gcd(a,m)|b時,有解
按照拓展歐幾里得演算法,可解得特解x=x0*b/gcd(a,m)就是原線性同餘方程的一個解
通解為所有模m/gcd(a,m)與x同餘的整數
求解同餘方程:noip2012:a*x=1(mod b)的最小整數解
#include<bits/stdc++.h> using namespace std; #define ll long long ll a,b,x,y; ll exgcd(ll a,ll b,ll &x,ll &y){ if(!b){x=1;y=0;return a;} ll d=exgcd(b,a%b,x,y); ll z=x; x=y,y=z-y*(a/b); return d; } int main(){ cin >> a >> b; exgcd(a,b,x,y);//x可能是負數 cout << (x%b+b)%b<<endl; }