我好菜啊……
歐拉函數
歐拉函數φ(n),是小於n且和n互質的正整數(包括1)的個數。
性質:
1.對於質數n:
$φ(n)=n-1$
2..對於n=pk
$φ(n)=(p-1)*p^{k-1}$
3.積性函數的性質:
對於互質的m,n,有:
$φ(n*m)=φ(n)*φ(m)$
4.歐拉函數的計算式:
$φ(n)=n*\Pi (1-\frac{1}{p_i})$
5.求小於n且與n互質的數的和:
$S=n*φ(n)/2$
歐拉定理
對於互質的a,m,有:
$a^{\varphi (m)}\equiv 1(mod\ m)$
可以看出費馬小定理是歐拉定理的特殊情況。
歐拉定理可以用於指數取模,即$x^y\ \equiv x^{y\ mod\ \varphi (p)}\ (mod\ p)$,p為質數
歐幾里得定理
$gcd(a,b)=gcd(b,a\ mod\ b)$
擴展歐幾里得
已知a,b,求解一組x,y,使他們滿足$ax+by=gcd(a,b)$
證明:
ax+by=gcd(a,b);
1. (1) $a = 0$,$ax+by = gcd(a,b) = gcd(0,b) = b$,
此時$x = 0$(此時x的值是任意的),$y = 1$;
(2)$b = 0$,$ax + by = gcd(a,b) = gcd(a,0) = a$,
此時$x = 1,y = 0$(此時y的值是任意的);
2.a和b都不為0時
$ax1 + by1 = gcd(a, b)$
由歐幾里德定理:$gcd(a,b) = gcd(b, a\% b)$得
$ax1 + by1 = gcd(a,b) = gcd(b, a\% b)$ 即:
$bx2 + a\% by2 = gcd(b, a\% b) = ax1 + by1$
$a \% b = a - a/b*b$;
$ax1 + by1 = bx2 + (a - a/b*b)y2$;
$=bx2 + ay2 - a/b*b*y2$;
$=ay2 + b(x2-a/b*y2)$;
所以:$x1 = y2,y1 = x2 - a/b*y2$
代碼

int exGcd(int a,int b,int &d,int &x,int &y) { if(!b) { d=a;x=1;y=0; } else { gcd(b,a%b,d,y,x); y-= x*(a/b); } }
求解$ax+by=c$時:

int exgcd(int a,int b,int &x,int &y,int c) { if(!b) { x=c/a; y=0; return a; } int g=exgcd(b,a%b,y,x,c); y-=a/b*x; return g; }
費馬小定理
對於質數p,任意整數a,且a、p互質,有:
$a^p\equiv a(mod\ p)$,即$a^{p-1}\equiv 1(mod\ p)$
乘法逆元
除以一個數再取模等同於乘以這個數的逆元再取模
即
$(a/b)\ mod\ p=(a*inv[b])\ mod\ p$
一個數 x 在模 p 的條件下不一定有逆元, x 關於 p 的逆元存在 當且僅當 x 和 p 互質
求逆元的方法:
1.費馬小定理+快速冪
由費馬小定理易得 $a*a^{p-2}\equiv 1(mod\ p)$
所以$a^{p-2}$即為所求(要求a、p互質!)
2.線性推逆元
求1!~n!的逆元:
$inv[i] =inv[i+1]*(i+1) (mod\ p)$

inline void get_finv() { fac[1]=finv[0]=1; for(int i=2;i<=n;++i;++i) fac[i]=fac[i-1]*i%mod; finv[n]=quick_pow(fac[n],mod-2); for(int i=n-1;i;--i) finv[i]=finv[i+1]*(i+1)%mod; }
證明:
fac[i] * inv[i] ≡1 (mod p) fac[i+1] * inv[i+1] ≡1 (mod p) => fac[i]* (i+1) * inv[i+1] ≡1(mod p) 由 同余的除法原理可得 : inv[i] ≡inv[i+1] * (i+1) 推導完畢
求1~n的逆元:
$inv[i]=inv[p\ mod\ i] * (- p/i) (mod\ p)$

inline void get_inv() { inv[0]=inv[1]=1; for(int i=2;i<=n;++i) inv[i]=inv[mod%i]*(mod-mod/i)%mod; }
證明:
令 s = p/i , t = p%i , 則有: s*i + t = p (顯然) 然后 s*i + t ≡ 0 (mod p) 移項得 t ≡ -s*i (mod p) 同除以 t * i 得 t / (t*i) ≡ -s*i / (t*i) (mod p) 將除法轉化為乘法 => inv[i] ≡ -s * inv[t] (mod p) 於是將 s=p/i , t=p%i帶入就可以得到: inv[i] ≡ inv[p%i] * (-p/i) (mod p) 推導完畢
3.擴展歐幾里得
$axΞ1(mod\ b)$
-->$ax+by=1$
利用擴歐求解

//轉載 from Judge #define ll long long const int mod=; //同上 void ex_gcd(ll a,ll b,ll &x,ll &y){ if(!b){ x=1,y=0; return ; } ex_gcd(b,a%b,x,y); ll t=x; x=y,y=t-(a/b)*y; } //當然你也可以這么寫,更能體現公式: // ll X=x,Y=y; // x=Y,y=X-(a/b)*Y; inline ll inv(ll a){ ll inv_a,y; ex_gcd(a,mod,inv_a,y); return inv_a; }
中國剩余定理
求解同余方程組
xΞa1(mod m1)
xΞa2(mod m2)
xΞa3(mod m3)
......
xΞak(mod mk)
其中a1 a2 a3... ak兩兩互質
求x的最小非負整數解
定理內容
令$M=lcm(m_1,m_2,m_3,...m_k)$,即$M=m_1*m_2*m_3*...*m_k$
$t_i$為 $\frac{M}{m_i} t_i \equiv 1\ (mod\ m_i)$的最小非負整數解
則必有一解為
$x=\sum \limits _{i=1}^{k} a_i \frac{M}{m_i} t_i$
通解為$x+i×M$
最小非負整數解為$(M+x\ mod\ M)\ mod\ M$

//ti同余式的求解可以用擴展歐幾里得 void exgcd(int a,int b,int &x,int &y) { if(b==0){ x=1; y=0; return;} exgcd(b,a%b,x,y); int tp=x; x=y; y=tp-a/b*y; } int china() { int ans=0,lcm=1,x,y; for(int i=1;i<=k;++i) lcm*=b[i]; for(int i=1;i<=k;++i) { int tp=lcm/b[i]; exgcd(tp,b[i],x,y); x=(x%b[i]+b[i])%b[i];//x要為最小非負整數解 ans=(ans+tp*x*a[i])%lcm; } return (ans+lcm)%lcm; }
擴展中國剩余定理
用於解決m1,m2,m3...mn不互質的情況。
考慮只有m1,m2的情況:
設解為x
可得
$x=a_1+k_1*m_1 ; x=a_2+k_2*m_2$
$a_1+k_1*m_1 = a_2+k_2*m_2$
$k_2*m_2-k_1*m_1=a_1-a_2$
形式與擴歐可解的同余方程十分相似
設g=gcd(m1,m2)
若$a_1-a_2$不是g的倍數 就無解遼(詳見exgcd解同余方程有解的條件)
否則解這個同余方程
最終的解$\times \frac{c}{g}$可得$k_1$
由$x=-k_1\times m_1+a_1$解得x
則通解$X=x+k\times lcm(m_1,m_2)$
最終得到$x=x_0 (mod lcm(m_1,m_2))$
以此類推,解n次擴歐得到最終解。

#include<cstdio> #include<iostream> #include<cstring> using namespace std; typedef long long ll; const int N=100005; int n; ll m[N],a[N]; ll exgcd(ll a,ll b,ll &x,ll &y) { if(!b) { x=1;y=0; return a; } ll gcd=exgcd(b,a%b,y,x); y-=(a/b)*x; return gcd; } ll excrt() { ll x,y,lcm=m[1],ans=a[1],gcd; for(int i=2;i<=n;i++) { gcd=exgcd(lcm,m[i],x,y); if((ans-a[i])%gcd)return -1; x=(ans-a[i])/gcd*x%m[i]; ans-=lcm*x; lcm=lcm/gcd*m[i]; ans%=lcm; } return (ans%lcm+lcm)%lcm; } void work() { for(int i=1;i<=n;i++) scanf("%lld%lld",&m[i],&a[i]); cout<<excrt()<<endl; } int main() { while(scanf("%d",&n)==1)work(); return 0; }
排列組合
排列數
從n個不同元素中取出m個元素(m<=n)的所有不同排列的個數。
$A_n^m=n(n-1)(n-2)\cdots(n-m+1)=\frac{n!}{(n-m)!},\quad n,m\in \mathbb{N}^* ,\text{並且}m\leq n$
特別地,規定0!=1.
組合數
從n個不同元素中取出m個元素(m<=n)的所有不同組合的個數。
$C_n^m=\frac{A_n^m}{A_m^m}=\frac{n(n-1)(n-2)\cdots (n-m+1)}{m!}=\frac{n!}{m!(n-m)!},\quad n,m\in \mathbb{N}^* ,\text{並且}m\leq n$
規定$C_n^0=C_n^n=1$
二項式定理
常見形式
$(x+1)^n=\sum_{i=0}^{n} C(n,i) ~ x^i$
證明:
(x+1)n=(x+1)*(x+1)*...*(x+1)
從這n個(x+1)中選擇n次,每次只可能選出x或1。
那么答案即為每次選出n個元素相乘后將結果累加
而從n個(x+1)中選出i個x的情況數即為
$C_n^i$
證畢。
Lucas定理
定理內容
證明
(咕咕咕)
代碼

ll C(ll x,ll y,ll mod) { if(x<y)return 0; return fac[x]*qpow(fac[y],p-2,p)%p*qpow(fac[x-y],p-2,p)%p; } ll lucas(ll x,ll y,ll p) { if(!y)return 1; return C(x%p,y%p,p)*lucas(x/p,y/p,p)%p; }
莫比烏斯反演(強行NOIP前)
兩類基本形式:
$\begin{aligned} &(1).F(n)=\sum_{d|n}f(d)\Rightarrow f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d})&\\ &(2).F(n)=\sum_{n|d}f(d)\Rightarrow f(n)=\sum_{n|d}\mu(\frac{d}{n})F(n)(最常用)&\\ \end{aligned}$
范德蒙恆等式
$\sum_{i=0}^{k} C_n^i C_m^{k-i}=C_{n+m}^k$
φ(n)=n−1