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'); }總結
- 上一篇: 特征选择算法之ReliefF算法pyth
- 下一篇: 获取正在运行的服务