日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 数论

發布時間:2023/12/9 c/c++ 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 数论 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.一些定理及證明

?

1.費馬小定理

若p為素數,則有??

2.歐拉定理

若a,p互質,則有??

證明:

令為p的歐拉函數

設a mod p的簡化剩余系為??

因為a,p互質,所以a*p一定在a mod p的簡化剩余系里

故??

所以??, 故歐拉定理成立

因為p為質數,所以?

故?,費馬小定理成立

歐拉定理的推論:若a,p互質,則有??

證明:令?,

故??,推論成立

2.拓展歐幾里得

1.bezout定理:一定存在整數使ax+by=gcd(a,b)

證明 當b=0時,x=1,y=0,命題成立

當b!=0時,gcd(a,b)=gcd(b,a mod b)

假設有一組解使ax+by=gcd(b,a mod b)成立

故?

故?

所以一定有一組整數解為?

實現代碼:

int exgcd(int a,int b,&x,&y){if(!y){x=1,y=0;return a;}int gcd=exgcd(b,a%b,x,y);int ty=x;x=y,y=ty-a/b*y;return gcd; }

對于一般的不定方程ax+by=d,當且僅當 gcd(a,b)|d時方程有整數解

一組整數解為??

所有整數解為??

證明:gcd(a,b)|a,gcd(a,b)|b

所以新的x,y一定是整數

將? ??帶入不定方程

因為?

解得? ?

逆元

因為除法運算不能取模,所以需要找到一個合適的工具來代替取模運算中的除法,就引進了逆元

,inv就是x在模m意義下的逆元

在模m的意義下,x*inv的值是1,就相當于x*1/x,同理,k為任意整數,k*inv在模m的意義下就相當于k*1/x

當且僅當x與m互質的情況下才有逆元

證明:

根據bezout定理,當且僅當gcd(x,m)|1時方程有解

故gcd(x,m)=1,也就是x與m互質

3.中國剩余定理

?設m1,m2,m3...兩兩互質,且?

求x最小值?

令? ?

則? ?

證明:對于i=k時,m/m[i]保證了這個答案加上對其他項沒有影響,其他保證了這一項加上后在ans對m[i]取模時答案為a[i](m/m[i]*inv在模m[i]的意義下余1,故這個式子在模m[i]的情況下為a[i]

for(int i=1;i<=n;i++){ll mi=mulmod/a[i];ll x,y;ll gcd=exgcd(mi,m[i],x,y);//求出在模m[i]意義下的逆元x=(x%m[i]+m[i])%m[i];ans+=mi*x*a[i]; }

4.拓展中國剩余定理

還是這種形式,但是模數不一定互質,這時候就不能用中國剩余定理了

因為若余數不兩兩互質,??m/m[i]就不會和m[i]互質,就找不到?

所以中國剩余定理就不再適用

這時考慮構造特解,對于???,令?,ans為前i-1組方程的解

那么需要找到一個x使??,那么ans+x*lcm一定是前i組方程的通解

因為?

就需要求出x的值,然后用ans+x*lcm更新ans

mul=1;for(int i=1;i<=n;i++){ll gcd=exgcd(mul,b[i],x,y);ll d=a[i]-ans;x=x*(d/gcd);ll ty=b[i]/gcd;x=(x%ty+ty)%ty;ans=ans+x*mul;mul=b[i]/exgcd(b[i],mul,x,y)*mul;}

NOI2018 屠龍勇士

繼續拓展

繼續構造解,對于???, 令,ans為前i-1組方程的解

那么需要找到一個x使???,那么ans+x*lcm一定是前i組方程的通解

因為?

求出x,并且使ans=ans+x*lcm

其他部分實現都很簡單吧

#include<bits/stdc++.h> using namespace std; typedef __int128 ll; ll read(); void write(ll x); int t; ll a[100010],b[100010],p[100010],jl[100010],n,m; ll x,y,ans,mul; void excrt(); ll exgcd(ll a,ll b,ll &x,ll &y); int main(){scanf("%d",&t);while(t--){ans=0;mul=1;n=read(),m=read();for(int i=1;i<=n;i++) a[i]=read();for(int i=1;i<=n;i++) p[i]=read();for(int i=1;i<=n;i++) jl[i]=read();for(int i=1;i<=m;i++) b[i]=read();if(p[1]==1){multiset<int>s;s.clear();for(int i=1;i<=m;i++) s.insert(b[i]);for(int i=1;i<=n;i++){multiset<int>::iterator it=s.upper_bound(a[i]);it==s.begin()?it:it--;s.erase(it);ll bnow=(*it); ans=max(ans,(ll)ceil((double)a[i]/bnow));s.insert(jl[i]);}write(ans);}else{excrt();if(ans!=-1) write(ans);else printf("-1");} putchar('\n');}return 0; } void excrt(){multiset<ll>s;s.clear();for(int i=1;i<=m;i++) s.insert(b[i]);for(int i=1;i<=n;i++){multiset<ll>::iterator it=s.upper_bound(a[i]);if(it!=s.begin()) it--;s.erase(it);ll bnow=(*it);ll gcd=exgcd(mul*bnow,p[i],x,y);ll d=(a[i]-ans*bnow%p[i]+p[i])%p[i];if(d%gcd){ans=-1;return ;}x=x*(d/gcd);ll ty=p[i]/gcd;x=(x%ty+ty)%ty;ans+=mul*x; mul=mul*(p[i]/gcd);s.insert(jl[i]);}ans=(ans%mul+mul)%mul; } ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1,y=0;return a;}ll gcd=exgcd(b,a%b,x,y);ll ty=x;x=y,y=ty-a/b*y;return gcd; }ll read(){ll a=0;char ch=getchar();while(ch<'0'||ch>'9') ch=getchar();while(ch>='0'&&ch<='9') a=a*10+ch-'0',ch=getchar();return a; } void write(ll x){if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10+'0'); }

總結

以上是生活随笔為你收集整理的c++ 数论的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。