1. 程式人生 > 實用技巧 >數論雜記——裴蜀定理、拓展歐幾里得

數論雜記——裴蜀定理、拓展歐幾里得

裴蜀定理其實就是證明了一個二元一次方程

如果 x y 同時有解

那麼一定會有

模板題洛谷P4549

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 2e5+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int n,i,a[maxn],ans; int
main() { n=read(); for (i=1;i<=n;i++) a[i]=read(); for (i=1;i<=n;i++) { if (a[i]<0) a[i]=-a[i]; ans=__gcd(ans,a[i]); } cout<<ans<<endl; return 0; }
View Code

而拓展歐幾里得則是在裴蜀定理的基礎上建立的

拓展歐幾里得的證明過程比較長,這裡貼出證明過程比較清晰的文章。https://www.zybuluo.com/samzhang/note/541890

實際上做的就是求解 的過程

void exgcd(ll a,ll b,ll &d,ll &x,ll &y){ //擴歐,ax+by=gcd(a,b),d存gcd
    if(!b)d=a,x=1,y=0;
    else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
View Code

模板洛谷P1082

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e3+7;
const int INF = 0x3f3f3f3f; 
const int mod = 1e9+7;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
ll a,b,x,y;
void exgcd(ll a,ll b,ll &x,ll &y)
{
    if (!b) x=1,y=0;
    else exgcd(b,a%b,y,x),y-=x*(a/b);
}
int main()
{
    a=read(),b=read();
    exgcd(a,b,x,y);
    cout<<(x%b+b)%b<<endl;
    return 0;
 } 
View Code

稍微加深P1516

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e3+7;
const int INF = 0x3f3f3f3f; 
const int mod = 1e9+7;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
ll x_1,y_1,m,n,l,d,x,y;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if (!b) d=a,x=1,y=0;
    else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
int main()
{
    x_1=read(),y_1=read(),m=read(),n=read(),l=read();
    if (n-m<0) swap(x_1,y_1);
    exgcd(abs(n-m),l,d,x,y);
    if ((x_1-y_1)%d!=0) printf("Impossible");
        else printf("%lld\n",((x*((x_1-y_1)/d))%(l/d)+(l/d))%(l/d));
    return 0;
}
View Code

兩者結合

牛客2020多校訓練day3 F

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 505;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int a,b,g,t;
ll c,d,e,f;
void exgcd(ll a,ll b,ll &x,ll &y){ //擴歐,ax+by=gcd(a,b),d存gcd
    if(b==0)x=1,y=0;
    else exgcd(b,a%b,y,x),y-=x*(a/b);
}
int main()
{
    t=read();
    while (t--)
    {
        a=read(),b=read();
        g=__gcd(a,b);
        if (g!=1) 
        {
            printf("%d %d %d %d\n",a/g+1,b/g,1,b/g);
            continue;
        }
        d=0;f=0;
        for (int i=2;i*i<=b;i++)
        {
            if (b%i==0 && __gcd(i,b/i)==1)
            {
                d=1ll*i,f=1ll*(b/i);
                break;
            }
        }
        if (d==0 && f==0) printf("-1 -1 -1 -1\n");
        else
        {
            exgcd(f,d,c,e);
            c*=1ll*a,e*=1ll*a;
            if(c>0&&e<0) printf("%lld %lld %lld %lld\n",c,d,-e,f);
                else printf("%lld %lld %lld %lld\n",e,f,-c,d);
        }
    }
    return 0;
}
View Code