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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解数论从入门到入土

發布時間:2023/12/31 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解数论从入门到入土 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本蒟蒻第一次講課,由于比較匆忙所以沒有及時準備課件,在此表示抱歉…
聽說他們講課都是啥都沒有 在那兒嘮嗑202020分鐘然后問:有沒有不會的 不會的自己學 就完事了??233323332333真是負責

前景提要

這是一篇數論000零起點到負無窮,從入門到入土的博客 請大家做好心理準備

聽說CCC層要講數論?
哈 作為前數學競賽生的我當然要搶著講了 于是跟pjtpjtpjt大哥蹭了一下
本著放松隨便講一講的心態 我問了我們這邊的lysslysslyss小寶寶

但是pjtpjtpjt去自由啊…那就我自己寫吧…

tips:tips:tips:現在要講的基本涉及的都是整數 所用的字母除聲明外也都表示整數

Part1.Part1.Part1.整數的常識

一、整除

1.設aaabbb是給定的數,b≠0,b\neq0b=0。若存在整數c,c,c使得a=bc,a=bc,a=bc則稱bbb整除a,a,a記作b∣a,b\mid a,ba反之,,,則稱bbb不能整除a,a,a記作b?ab\nmid ab?a
2.一些性質:

a. 若a∣ba|bab,且b∣cb|cbc,則a∣ca|cac
b. 若b∣ab|aba,且b∣cb|cbc,則b∣(a±c)b|(a\pm c)b(a±c)
c.若c∣ac|aca,且c∣bc|bcb,則對于任意整數m、n,有c∣(ma+nb)c|(ma+nb)c(ma+nb)

二、素數與合數

\,\,\,\,\,\,\,\,對于一個正整數,如果它有且僅有1和它自己兩個約數,那么我們稱這個數為素數。如果有兩個以上的約數,那么我們稱這個數為合數。注意:1既不是素數也不是合數

先植入一個沒什么用的定理,它叫素數定理:
小于x的素數的個數近似等于x/ln(x)…

現在我們想想如何求素數

1.考慮暴力枚舉

如果2?n2 -\sqrt{n}2?n?每個數都不是nnn的因子,那么nnn就是質數了。
復雜度O(n)O(\sqrt{n})O(n?)

那么我們來看一道題:
1?n1-n1?n內的素數。 n<=1000000n<=1000000n<=1000000

用上述的算法那是要跑100s100s100s的 所以我們就需要換一個高效的算法

2.篩法求素數
基本思路是:素數的倍數不是素數
\,\,\,\,\,\,\,\, 1不是素數首先把它篩掉,剩下的數中最小的數一定是素數,然后去掉它的倍數。
vis[i]vis[i]vis[i]表示iii是否被訪問過,cnt,cnt,cnt表示現在素數的數量,prime,prime,prime數組存的是從小到大的素數
代碼:

for(int i=2;i<=n;i++){if(!vis[i]){prime[++cnt]=i;for(int j=1;j*i<=n;j++)vis[i*j]=true;} }

這回由O(nn)O(n\sqrt{n})O(nn?)變成了O(nlogn)O(n\,log_n)O(nlogn?)
但是我們注意到,這樣篩會篩重很多次。
我們拿757575舉例 :在篩到素數333時我們把它篩除 在篩到素數555時我們又會篩除一次 這樣會浪費大量的時間,如何優化呢?
3.線性篩
基本思路是:在篩法的基礎上 我們讓每一個合數只能被他自己最小的素數篩到
如何實現這個優化呢?
看代碼

for(int i=2;i<=n;i++){if(!vis[i])prime[++cnt]=i;for(int j=1;j<=cnt&&i*prime[j]<=n;j++){vis[i*prime[j]]=true;if(i%prime[j]==0)break;} }

在篩到每個數時 我們把小于它的最小質數的所有質數倍數的數都篩掉 這樣就能保證每個數是被它自己最小的質因子篩掉

Part2.Part2.Part2.gcd&lcmgcd\&lcmgcd&lcm

gcdgcdgcd是啥?lcmlcmlcm是啥?某黨?

gcdgcdgcd指的是greatestcommondivisorgreatest\,\,common\,\, divisorgreatestcommondivisor就是最大公約數。
lcmlcmlcm指的是LeastCommonMultiple,Least\,\,Common\,\,Multiple,LeastCommonMultiple即最小公倍數。

一、最大公約數

最大公約數是數論中一個重要的概念

aaabbb不全為零,,,同時整除aaabbb的整數稱為他們的公約數,,顯然aaabbb的公約數只有有限多個,,我們將其中最大的一個稱為aaabbb的最大公約數表示,,用符號(a,b)(a,b)(a,b)表示。顯然,,最大公約數是一個正整數。
(a,b)=1(a,b)=1(a,b)=1,,我們稱aaabbb互質(((互素),),)這種情形特別重要。

那么問題來了 我們怎么求最大公約數呢?
通常用輾轉相除法來寫 我的個人喜好是用遞歸
輾轉相除法是不都會…? 算了算了 好好講講吧
我們可以很顯然地理解這個等式:

gcd(a,b)=gcd(a?b,b)gcd(a,b)=gcd(a-b,b)gcd(a,b)=gcd(a?b,b)

但是呢 這么一次一次減太慢了 所以我們一次能減多少就減多少
就相當于直接除 這就是簡述版的輾轉相除

int gcd(int a, int b){if(b==0)return a;else return gcd(b,a%b); }

我不會告訴你們algorithm庫里有可以直接用的__gcd
輾轉相除在后面個的擴展gcdgcdgcd中還是很有用的
上兩個題吧

luoguP1372
簡述版題意:給你個nnnkkknnn個數中取kkk個的最大公約數最大

Solution:Solution:Solution:設這 kkk個數的最大公約數為gcdgcdgcd
則第kkk個數最小為k×gcdk×gcdk×gcd 所以k×gcd≤nk×gcd\leq nk×gcdn
那么gcd≤nkgcd\leq\frac{n}{k}gcdkn? 顯然最大的gcd=?nk?gcd=\lfloor\frac{n}{k}\rfloorgcd=?kn??

#include<iostream> using namespace std; int main() {int n,k;cin>>n>>k;cout<<n/k<<endl; }

luoguP2090
對于一個數字對(a, b),我們可以通過一次操作將其變為新數字對(a+b, b)或(a, a+b)。

給定一正整數n,問最少需要多少次操作可將數字對(1, 1)變為一個數字對,該數字對至少有一個數字為n。
Solution:Solution:Solution:
注意到等式gcd(a,b)=gcd(a,a+b)gcd(a,b)=gcd(a,a+b)gcd(a,b)=gcd(a,a+b)
所以找到111n?1n-1n?1gcd(a,b)gcd(a,b)gcd(a,b)遞歸層數最少的就好咯
在這兒推一下那天的模擬賽的解題報告 其中就有這道題 模擬賽不是很難大家可以看看
最后有彩蛋哦
地址在這!:題解

#include<bits/stdc++.h> using namespace std; #define inf int(1e8) inline void read(int &x){int 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<<3)+(s<<1)+(ch&15);ch=getchar();}x=s*w; } int gcdd(int a, int b){if(!b)return inf;if(b==1)return a-1;return gcdd(b,a%b)+a/b; } int n,now=inf; int main(){read(n);for(int i=1;i<=(n+1)/2;i++)now=min(now,gcdd(n,i));printf("%d\n",now); }

二、最小公倍數

那么我們再簡單地談談最小公倍數
a、ba、bab是兩個非零正整數,,一個同時為a、ba、bab的倍數的書稱為他們的一個公倍數,,,兩個數的公倍數顯然有無窮多個,,,我們把這其中的最小的正整數稱為他們的最小公倍數

那最小公倍數就很好求了

lcm(a,b)=abgcd(a,b)lcm(a,b)=\frac{ab}{gcd(a,b)}lcm(a,b)=gcd(a,b)ab?

UPD:UPD:UPD:昨天講到這里哦!
經過一 天

Part3.Part3.Part3.同余及應用

一、同余

同余是數論中的一個重要概念,應用極為廣泛。
nnn是給定的正整數,若整數a、ba、bab滿足n∣(a?b),n\mid(a-b),n(a?b)則稱aaabbbnnn同余,,,記作

a≡b(modn)a\equiv b(mod\,\,n)ab(modn)

反之,則稱aaabbbnnn不同余,,,記作

a≡?b(modn)a\not\equiv b(mod\,\,n)ab(modn)

很顯然,aaabbbnnn同余的充分必要條件是aaabbbnnn除得的余數相同。

同余式的幾個性質:

  • 反身性:a≡a(modn)a\equiv a(mod\,\,n)aa(modn)
  • 對稱性:若a≡b(modn),a\equiv b(mod\,\,n),ab(modn)b≡a(modn)b\equiv a(mod\,\,n)ba(modn)
  • 傳遞性:若a≡b(modn),a\equiv b(mod\,\,n),ab(modn)b≡c(modn),b\equiv c(mod\,\,n),bc(modn)a≡c(modn)a\equiv c(mod\,\,n)ac(modn)
  • 可加性:若a≡b(modn),a\equiv b(mod\,\,n),ab(modn)c≡d(modn),c\equiv d(mod\,\,n),cd(modn)a±c≡b±d(modn)a\pm c\equiv b\pm d(mod\,\,n)a±cb±d(modn)
  • a≡b(modn),a\equiv b(mod\,\,n),ab(modn)c≡d(modn),c\equiv d(mod\,\,n),cd(modn)ac≡bd(modn)ac\equiv bd(mod\,\,n)acbd(modn)
    運用這幾個性質 我們把同余應用在信息中的數論
  • 二、快速冪

    給定a、n、ma、n、manmanmodka^n\,\,mod\,\,kanmodk
    考慮樸素算法 用循環一個一個累乘 可以在O(n)O(n)O(n)的時間內求出答案
    不過似乎沒什么用 這一點都不快速
    那么我們來點快的
    考慮到a2n=an2a^{2n}={a^n}^{2}a2n=an2所以我們可以兩兩配對地乘
    所以
    1.1.1.當n是奇數時,那么有 an=a?an?1a^{n} = a * a^{n-1}an=a?an?1

    2.2.2.當n是偶數時,那么有 an=an2?an2a^n = a^\frac{n}{2}* a^\frac{n}{2}an=a2n??a2n?
    上代碼

    int quickpow(int a, int n, int m){int ret=1;while(b){if(b&1)(ret*=a)%=m;(a*=a)%=m,n>>=1;} }

    時間復雜度:O(logn)O(log_n)O(logn?)
    10.2323:1210.23\,\,\,23:1210.2323:12今天先寫到這兒 明天應該講不到這兒

    三、擴展歐幾里得

    引題:給定a、b、c,a、b、c,abc求使得ax+by=cax+by= cax+by=c成立的最小正整數解x、y,x、y,xy如果無解則輸出lyswanlyswanlyswan
    講真的 我是從這個題開始認識到信息真的是一門競賽…

    Solution:Solution:Solution:
    1.1.1.首先考慮是否有解:當gcd(a,b)∣cgcd(a,b)\mid cgcd(a,b)c時方程才有解
    2.2.2.所以我們先不管ccc到底是gcd(a,b)gcd(a,b)gcd(a,b)的幾倍 直接給
    我們考慮如何搞這個方程:
    首先看這個方程:bx+(a%b)y=cbx+(a\%b)y= cbx+(a%b)y=c這樣以此類推
    最后會得到gcd(a,b)x=cgcd(a,b)x= cgcd(a,b)x=c此時x=1x=1x=1
    對于a′=b,b′=a%ba' = b, b' = a\% ba=b,b=a%b而言,我們求得x,yx, yx,y使得a′x+b′y=gcd(a′,b′),a'x + b'y = gcd(a', b'),ax+by=gcd(a,b) 由于b′=a%b=a??ab?×bb' = a \% b = a - \lfloor\frac{a}{b}\rfloor ×bb=a%b=a??ba??×b
    所以可以推得ay+b(x??ab?×y)=gcd(a,b)ay +b(x - \lfloor\frac{a}{b}\rfloor ×y) = gcd(a, b)ay+b(x??ba??×y)=gcd(a,b)
    即一組通解為x=y,y=x??ab?×yx=y,y=x - \lfloor\frac{a}{b}\rfloor ×yx=y,y=x??ba??×y

    問題來了 我們怎么用代碼實現呢?
    注意到我們方程的變形用的是gcdgcdgcd函數輾轉相除,方程的通解是一步一步遞歸才能得到 所以用遞歸版的歐幾里得順便求得。
    這個就叫擴展歐幾里得 上代碼:

    void extended_gcd(int a, int b, int &x, int &y){if(b==0){x=1,y=0;return;}extended_gcd(b,a%b,x,y);int t=y;y=x-(a/b)*y,x=t; }

    最后的x,yx,yx,y就是解 不過出來可能會是一個負數 求最小正整數解還要再加上一個modmodmod

    這個東西其實真的很有用的 我們看一道題
    NOIP2012NOIP2012NOIP2012同余方程
    題意:求關于 xxx的同余方程 ax≡1(modb)a x \equiv 1 \pmod {b}ax1(modb)的最小正整數解。

    Solution:Solution:Solution:轉化為ax+by=1ax+by=1ax+by=1 就變成了擴展歐幾里得…
    代碼:

    #include<cstdio> int t,c,d,x,y; void exgcd(int a, int b, int &x, int &y) {if(a%b==0){x=0;y=1;return;}exgcd(b,a%b,x,y);t=x;x=y;y=t-a/b*y; } int main() {scanf("%d%d",&c,&d);exgcd(c,d,x,y);while(x<=0){x+=d;}printf("%d\n",x); }

    四、歐拉函數

    歐拉函數,即φ(x)φ(x)φ(x),簡單說它表示從1?n1-n1?n中和它互質的數的個數
    歐拉函數在各種玄學定理中經常出現,有的題中gcd=1gcd=1gcd=1 的情形往往可以轉化為歐拉函數
    如何求歐拉函數
    1.1.1.單個數歐拉函數的求解公式:
    對于一個數x=∏i=1npiαi,x=\prod \limits_{i=1}^{n} p_{i}^{\alpha _i},x=i=1n?piαi??那么φ(x)=x∏i=1n(1?1pi)φ(x)=x\prod \limits_{i=1}^n (1-\frac{1}{p_i})φ(x)=xi=1n?(1?pi?1?)
    至于為啥有興趣的自己推 不難推,這里就不贅述了。主要是…我現在要碼不完了啊啊估計明天也講不完了所以直接過吧…求饒.jpg.jpg.jpg
    2.2.2. 線性求 1?n1-n1?n 所有數的歐拉函數(((即歐拉篩)))
    上述求解歐拉函數不是沒有用 實在是太磨嘰…又要分解質因數,又要求乘積,還有分數…沒看我代碼都沒給嗎2333 但有時候這個式子推一些性質很有用的
    我們歐拉篩之前先要了解幾個性質:
    a.a.a.對于質數ppp,有φ(p)=p?1φ(p)=p-1φ(p)=p?1 顯然…
    b.b.b.(n,m)=1(n,m)=1(n,m)=1時,有φ(n×m)=φ(n)×φ(m)(φ(n×m)=φ(n)×φ(m)(φ(n×m)=φ(n)×φ(m)(即歐拉函數是但不完全是積性函數))),特別地,當2?n2\nmid n2?n時,φ(2n)=φ(n)φ(2n)=φ(n)φ(2n)=φ(n)
    用上面的定義式這個顯然成立
    c.c.c.m∣nm\mid nmn時,φ(m×n)=m×φ(n)φ(m×n)=m×φ(n)φ(m×n)=m×φ(n)
    用定義式回去自己推不會問我…
    那么這些性質我們了解之后,就可以篩篩篩篩篩篩了
    首先想一想 上面的性質是不是有點眼熟? ppp 為質數,n%m=0n\%m=0n%m=0
    沒錯就是線性篩,我們可以在線性篩素數的時候,運用這三條性質來維護歐拉函數,具體看代碼 我要講不完了!!

    euc[1]=1; for(int i=2;i<=n;i++) {if(!vis[i])euc[i]=i-1,prime[++cnt]=i;for(int j=1;j<=cnt;j++){if(i*prime[j]>n)break;vis[i*prime[j]]=true;if(i%prime[j]==0){euc[i*prime[j]]=euc[i]*prime[j];break;}else euc[i*prime[j]]=euc[i]*euc[prime[j]];} }

    仔細體會其實不難
    上例題:
    題面找不到了 大哥們我錯了
    題意:給定nnn,求1≤x,y≤n1\leq x,y\leq n1x,yngcd(x,y)=1gcd(x,y)=1gcd(x,y)=1的數對個數
    這就用到我們前面講的 某些問題的gcd=1gcd=1gcd=1可以轉化為歐拉函數
    用式子寫出來就是:
    ∑i=1n∑j=1n(gcd(i,j)=1)\sum_{i=1}^n \sum_{j=1}^n (gcd(i,j)=1)i=1n?j=1n?(gcd(i,j)=1)
    =∑i=1nφ(i)=\sum_{i=1}^nφ(i)=i=1n?φ(i)
    所以只需要求出歐拉函數的前綴和即可

    五、逆元

    終于來到最有用的地方了…

    什么是逆元?
    對于一個數x,x,x它在模ppp意義下的逆元aaa,滿足ax≡1(modp),ax\equiv 1\pmod p,ax1(modp)
    這東西很有用 可以說沒有逆元數論少了靈魂
    看這個題:給定n,m,pn,m,pn,m,pnmmodp\frac{n}{m}mod\,\,pmn?modp
    如果你沒學逆元 你肯定懵逼:woc??woc??woc??分數還能取模?
    這就是逆元的妙處
    Solution:Solution:Solution:求出mmm在模ppp意義下的逆元aaa,答案為na%pna\%pna%p
    那么這么好用的一個東西 我們怎么求呢???
    求逆元的方法

    1.1.1.exgcdexgcdexgcd
    逆元滿足什么條件?ax≡1(modp)ax\equiv 1\pmod pax1(modp)?同余方程啊!exgcdexgcdexgcd顯然可行啊。
    性能分析:

    • 時間復雜度O(logmax(a,b))O(log_{max(a,b)})O(logmax(a,b)?) 不是太差
    • 適用范圍:只要存在逆元就可求,適用個數不多,當modmodmod很大很大時是個非常不錯唯一的選擇
    • 缺點:遞歸~討厭厭…這是最常見以及我最不愿意打的一個…

    2.2.2.快速冪
    快速冪怎么求逆元?
    那首先你需要了解一個定理—費馬小定理:

    ppp為素數,那么ap?1≡1(modp)a^{p-1}\equiv 1\pmod pap?11(modp)

    這個是怎么來的呢? 歐拉定理的推論
    歐拉定理(有時也叫作費馬小定理的一般式):

    aφ(p)≡1(modp)a^{φ(p)}\equiv 1\pmod paφ(p)1(modp)

    那歐拉定理怎么來的呢?有興趣自己查查(其實是來不及了!!
    接著說 因為ap?1≡1(modp)a^{p-1}\equiv 1\pmod pap?11(modp),所以ap?2a^{p-2}ap?2就是aaa的逆元
    性能分析:

    • 時間復雜度:O(logmod)O(log_{mod})O(logmod?)
    • 適用范圍:在modmodmod是素數!! 并且modmodmod不是太太太大大大的時候
    • 優點:比擴歐好寫,我最喜歡求逆元的方法之一
    • 缺點:如果modmodmod是合數相信沒有人無聊到篩一遍歐拉函數

    3.3.3. 線性求逆元
    放心放心 這次線性沒有篩 不用害怕
    原理:ppp是模數,我們現在要求的是iii的逆元
    ppp寫成p=k?i+rp=k?i+rp=k?i+r其中0<r<i0<r<i0<r<i(就是帶余除法)
    k=pi,r=p%ik=\frac{p}{i},r=p\%ik=ip?,r=p%i

    解釋一下 第二行是第一行兩邊都除iririr得到的
    總的來說就是一個公式:
    inv[i]=?(mod/i)?inv[mod%i]inv[i]=-(mod/i)*inv[mod\%i]inv[i]=?(mod/i)?inv[mod%i]邊界是inv[1]=1inv[1]=1inv[1]=1
    優點:
    a.a .a.O(n)O(n)O(n)的時間內求出1?n1-n1?n 的所有逆元 高效
    b.b.b.代碼好打 就一行
    c.c.c.沒有缺點
    代碼:

    inv[1]=1; for(int i=2;i<mod;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;

    回到前面的問題,現在我們會求逆元了,分數取模自然也就很水了
    有理數取余
    題意:給出一個有理數c=abc=\frac{a}{b}c=ba?,求cmod19260817c\ \bmod 19260817c?mod19260817c的值。

    Solution:Solution:Solution:直接求bbb的逆元,由于19260817是個質數,所以輸出a×bmod?2a×b^{mod-2}%moda×bmod?2就好了,由于a,ba,ba,b很大 所以需要處理一下:↓

    #include<cstdio> typedef long long ll; const ll mod=19260817; ll quickpow(ll a, ll b){ll ret=1;while(b){if(b&1)(ret*=a)%=mod;(a*=a)%=mod,b>>=1;}return ret; } ll n,m; ll getint(){char chr=getchar();ll x=0;while(chr<'0'||chr>'9')chr=getchar();while(chr>='0'&&chr<='9'){x=(x*10)%mod;chr=getchar();}return x; } int main(){n=getint(),m=getint();if(m==0)return printf("Angry!"),0;printf("%lld\n",n*quickpow(m,mod-2)%mod); }

    板子題
    題意:給定n,pn,pn,p1?n1-n1?n中所有整數在模ppp意義下的乘法逆元。
    Solution:Solution:Solution:沒有SolutionSolutionSolution,線性求逆元直接過

    #include<bits/stdc++.h> #define N 3000010 typedef long long ll; using namespace std; int inv[N],n,p; inline int read(){int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();};while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch&15);ch=getchar();};return f*x; } int main(){n=read();p=read();inv[1]=1;puts("1");for(int i=2;i<=n;i++){inv[i]=(ll)(p-p/i)*inv[p%i]%p;printf("%d\n",inv[i]);} }

    逆元是一種非常有用的工具 它可以和很多有用的定理結合在一起形成擴展定理

    六、中國剩余定理

    中國剩余定理,也稱孫子定理,話說昨天你們為什么對這個定理這么感興趣呢…?
    中國剩余定理能干啥呢?
    比如 一筐蘋果 三個三個吃最后剩兩個,四個四個吃最后剩三個,五個五個吃最后剩四個,求一共有多少個蘋果?
    答案是595959個.
    當然中國剩余定理不只這么簡單
    給定kkk以及kkkai、mia_i、m_iai?mi?求一個最小的正整數nnn滿足
    {n≡a1(modm1)n≡a2(modm2)...n≡ak(modmk)\begin{cases} n\equiv a_1(\mod m_1)\quad \\ n\equiv a_2(\mod m_2)\quad \\... \\ n\equiv a_k(\mod m_k)\quad \ \end{cases}????na1?(modm1?)na2?(modm2?)...nak?(modmk?)??
    其中(m1,m2,...,mk)=1(m_1,m_2,...,m_k)=1(m1?,m2?,...,mk?)=1
    如何求解呢?
    M=∏i=1kmiM=\prod_{i=1}^km_iM=i=1k?mi?,即MMM是所有mim_imi? 的最小公倍數
    對于每個方程,設pi=Mmip_i=\frac{M}{m_i}pi?=mi?M?
    tit_iti?為同余方程piti≡1(modmi)p_it_i\equiv 1(mod\,\,m_i)pi?ti?1(modmi?)的最小非負整數解
    則有一個解x=∑i=1kaiMmitix=\sum_{i=1}^ka_i\frac{M}{m_i}t_ix=i=1k?ai?mi?M?ti?
    ?通解為x+i?M(i∈Z)x+i?M(i∈Z)x+i?M(iZ)
    特別地,最小非負整數解為(x%M+M)%M(x\%M+M)\%M(x%M+M)%M
    自己推推 很好理解 盲猜時間應該不夠了 所以不講了 不會問我
    代碼實現:求tit_iti?那個同余方程時要用到擴展歐幾里得
    其他的…入門難度的代碼實現

    void ex_gcd(ll n, ll m, ll &x, ll &y){if(!m){x=1,y=0;return;}ex_gcd(m,n%m,y,x);y-=(n/m)*x; } ll CRT(){ll ans=0,lcm=1,x,y;for(int i=1;i<=k;i++)lcm*=b[i];for(int i=1;i<=k;i++){t[i]=lcm/b[i];ex_gcd(t[i],b[i],x,y);x=(x%b[i]+b[i])%b[i];ans=(ans+t[i]*a[i]%lcm*x%lcm)%lcm;}return (ans+lcm)%lcm; }

    例題例題例題:
    TJOI2009TJOI2009TJOI2009猜數字
    簡述題意:給個tttttt組數據,每組數據給kkk以及kkkai、mia_i、m_iai?mi?求最小的非負整數nnn,滿足對于任意的i,n?aii,n - a_iin?ai?能被bib_ibi?整除。

    Solution:Solution:Solution:板子題板子題板子題!!!
    從這個:

    推到這個:

    即:


    題中給的(b1,b2,...,bk)=1(b_1,b_2,...,b_k)=1(b1?,b2?,...,bk?)=1所以中國剩余定理可做。
    注意:
    1.1.1.直接乘爆longlonglong longlonglong要用快速乘,快速乘其實是慢速乘…具體跟快速冪差不多,看代碼
    2.2.2.直接快速乘會 TLETLETLE因為快速乘不能有負數,而題中說數可能為負數,所以如果是負數要加個modmodmod
    這兩個地方當時差點沒坑死我…
    代碼↓

    #include<bits/stdc++.h> using namespace std; typedef long long ll; inline ll quickpow(ll x, ll y, ll mod){ll ret=1;while(y){if(y&1)(ret*=x)%=mod;(x*=x)%=mod,y>>=1;}return ret; } inline ll quickmul(ll x, ll y, ll mod){if(x<0)x+=mod;if(y<0)y+=mod;if(y>x)swap(x,y);ll ret=0;while(y){if(y&1)(ret+=x)%=mod;(x+=x)%=mod,y>>=1;}return ret; } ll k,a[20],b[20],t[20]; void ex_gcd(ll n, ll m, ll &x, ll &y){if(!m){x=1,y=0;return;}ex_gcd(m,n%m,y,x);y-=(n/m)*x; } ll CRT(){ll ans=0,lcm=1,x,y;for(int i=1;i<=k;i++)lcm*=b[i];for(int i=1;i<=k;i++){t[i]=lcm/b[i];ex_gcd(t[i],b[i],x,y);x=(x%b[i]+b[i])%b[i];ans=(ans+quickmul(quickmul(t[i],a[i],lcm),x,lcm))%lcm;}return (ans+lcm)%lcm; } int main(){scanf("%lld",&k);for(int i=1;i<=k;i++)scanf("%lld",&a[i]);for(int i=1;i<=k;i++)scanf("%lld",&b[i]);printf("%lld\n",CRT()); }

    此外,當模數不是互質時,我們就會用到擴展中國剩余定理了,有興趣的可以自己學一下

    Part4.Part4.Part4.組合數學

    組合數學是信息中的數論的一個重要分支
    不過講不完了
    加我QQ:407694747QQ:407694747QQ:407694747免費一對一輔導,不容錯過…

    總結

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

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