数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群)
因为不会做目录所以请善用ctrl+F
本来想的是笔记之类的,写着写着就变成了资源整理
一些有的没的的前置
导数
(f'(x)=limlimits_{ riangle x ightarrow 0}frac{f(x+ riangle x)-f(x)}{ riangle x})
(sin x:cos x)
(cos x:-sin x)
(ln x:frac{1}{x})
(e^x:e^x)
(x^n:nx^{n-1})
(log_a^x:frac{1}{xln a})
(a^x:a^xln a)
([af(x)+bg(x)]'=af'(x)+bg'(x))
([f(x)g(x)]'=f(x)g'(x)+f'(x)g(x))
([frac{f(x)}{g(x)}]'=frac{f'(x)}{g(x)}-frac{f(x)g'(x)}{g^2(x)})
([f(g(x))]'=f'(g(x)) imes g'(x))
牛顿迭代
(x_i=x_{i-1}-frac{f(x_{i-1})}{f'(x_{i-1})})
泰勒展开
(f(x)=sumlimits_{i=0}^{infty }frac{f^{(i)}(x_0)(x-x_0)^i}{i!})
麦克劳林展开
(f(x)=sumlimits_{i=0}^{infty}frac{f^{(i)}(0)}{i!}x^i) (麦克劳林级数)
是泰勒公式的特殊形式。
几个常见泰勒展开
(ln(1-x)=sumlimits_{i}-frac{x^i}{i})
(e^x=sumlimits_{i=0}^{infty}frac{x^i}{i!})
(sin(x)=sumlimits_{i=0}^{infty}(-1)^ifrac{x^{2i+1}}{(2i+1)!})
(cos(x)=sumlimits_{i=0}^{infty}(-1)^ifrac{x^{2i}}{(2i)!})
(frac{1}{(1-x)^n}=sumlimits_{i=0}^{infty}inom{i+n-1}{n-1}x^i) (可以用生成函数理解)
一个结论:(e^{ix}=cos(x)+i imes sin(x))
拉格朗日插值
(sumlimits_{i=1}^{n}y_iprodlimits_{j!=i}frac{(x-x_j)}{(x_i-x_j)})
多项式操作/形式幂级数
多项式求逆
(C=B imes (2-AB))
(因为太常见我就不推了)
多项式开根
((B-C)=0)
(B^2+C^2+2BC=0)
(B^2+A+2BC=0)
(C=(A/B+B)/2)
这里插一个二次剩余的Cipolla算法
要求(x^2=n)
随一个(t),使得((t^2-n)^{(p-1)/2}=p-1)
设(I=t^2-n)
那么答案就是((t+sqrt I)^{(p+1)/2})
多项式(ln)
(B=lnA)
(B'=frac{A'}{A})
(不用倍增!当然倍增也不会错复杂度也一样)
多项式(exp)
(B=e^A)
(lnB=A)
(lnB-A=0)
(B=B-(lnB-A) imes B=B imes (1-lnB+A))
多项式求导
for(i=1;i<len;i++)b[i-1]=a[i]*i;
多项式求积分
for(i=1;i<len;i++)b[i]=a[i-1]*inv[i];
多项式快速幂
(B(x)=A(x)^n)
(lnB(x)=nlnA(x))
常数项不为(1)需要特殊处理。
https://blog.csdn.net/xyz32768/article/details/82832467
多项式除法
定义(A_R)满足(A_R[i]=A[n-i])。
(F(x)=Q(x)G(x)+R(x)) ((deg(F)=n,deg(G)=m,deg(Q)=n-m,deg(R)=m-1))
(F(frac{1}{x})=Q(frac{1}{x})G(frac{1}{x})+R(frac{1}{x}))
同乘(x^n),得(F_R(x)=Q_R(x)G_R(x)+R_R(x)x^{n-m+1})
(F_R(x)=Q_R(x)G_R(x)(mod x^{n-m+1}))
(Q_R=F_R/G_R)
多项式取模
(A mod B=A-lfloor frac{A}{B} floor A)
多项式多点求值
对于(F(x))和(x_1,x_2,...x_m)求出(F(x_1),F(x_2),...,F(x_m))。
思路就是分治,同时利用多项式取模减少多项式的次数。
先计算(G_{ls}=prodlimits_{i=l}^{mid}(x-x_i),G_{rs}=prodlimits_{i=mid+1}^r(x-x_i))
对于左边的所有(x_i),在(G_{ls})下的点值都是(0),因此可以把(F)变成(F mod G_{ls}),右边同理。
多项式快速插值
(F(x)=sumlimits_{i=1}^nfrac{prod_{j!=i}(x-x_j)}{prod_{j!=i}(x_i-x_j)}y_i)
考虑求出(prod_{j!=i}(x_i-x_j)),设(M(x)=prod_{i=1}^n(x−x_i)),那么我们就是要求(frac{M(x)}{x-x_i})。
(x=x_i),根据洛必达法则,得这个式子就等于(M'(x_i)),可以多点求值求出这个。
设(v_i=frac{y_i}{prod_{j!=i}(x_i-x_j)}),我们要求的就是(sumlimits_{i=1}^nv_iprod_{j!=i}(x-x_j))
同样分治即可。
板子:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mod 998244353
#define N 400050
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
int x=0; char s=nc();
while(s<'0') s=nc();
while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
return x;
}
int inv[N],ntt_w[2][N],mem[N*100],*ptr=mem;
int A[N],B[N],C[N],D[N],E[N],F[N],G[N],inv2=(mod+1)/2;
int qp(int x,int y=mod-2) {
int re=1;for(;y;y>>=1,x=ll(x)*x%mod)if(y&1)re=ll(re)*x%mod; return re;
}
int INV(int x) {return qp(x,mod-2);}
namespace Cipolla {
int I;
struct cp {
int x,y;
cp(){}
cp(int x_,int y_) {x=x_,y=y_;}
cp operator * (const cp &u) const {
return cp((ll(x)*u.x+ll(y)*u.y%mod*I)%mod,(ll(x)*u.y+ll(y)*u.x)%mod);
}
};
bool check(int x) {return qp(x,(mod-1)/2)==1;}
int Sqrt(int n) {
srand(123123); rand();
int t=rand()%mod;while(check((ll(t)*t-n)%mod))t=rand()%mod;
I=((ll(t)*t-n)%mod+mod)%mod;
cp re=cp(1,0),x=cp(t,1); int y=(mod+1)/2;
for(;y;y>>=1,x=x*x)if(y&1)re=re*x;
re.x=(re.x+mod)%mod;
return min(re.x,mod-re.x);
}
}
using namespace Cipolla;
void ntt_init(int l) {
int j,k,t,w,wn,i;
for(k=2;k<=l;k<<=1) {t=k>>1;
wn=qp(3,(mod-1)/k); w=1;
for(j=0;j<t;j++) ntt_w[0][t+j]=w,w=ll(w)*wn%mod;
wn=INV(wn); w=1;
for(j=0;j<t;j++) ntt_w[1][t+j]=w,w=ll(w)*wn%mod;
}inv[1]=1;for(i=2;i<=l;i++) inv[i]=ll(mod-mod/i)*inv[mod%i]%mod;
}
inline int Md(int x) {return x>=mod?(x-mod):x;}
void ntt(int *a,int len,int flg) {
int i,j,k,t,tmp,o=flg!=1;
static ull F[N];
for(i=0;i<len;i++)F[i]=(a[i]+mod)%mod;
for(i=k=0;i<len;i++) {
if(i>k) swap(F[i],F[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}for(k=2;k<=len;k<<=1) {
t=k>>1;for(i=0;i<len;i+=k) for(j=i;j<i+t;j++) {
tmp=F[j+t]*ntt_w[o][j-i+t]%mod; F[j+t]=(F[j]+mod-tmp); F[j]=(F[j]+tmp);
}
}
for(i=0;i<len;i++) a[i]=F[i]%mod;
if(flg==-1)for(tmp=inv[len],i=0;i<len;i++)a[i]=ll(a[i])*tmp%mod;
}
void get_inv(int*,int*,int,int);
void get_root(int*,int*,int,int);
void get_ln(int*,int*,int,int);
void get_exp(int*,int*,int,int);
struct cirno {
int *a,len;
cirno(){}
cirno(int l) {len=l,a=ptr,ptr+=l;}
void fix(int l) {len=l,a=ptr,ptr+=l;}
void rev() {reverse(a,a+len);}
void get_mod(int l) {int i;for(i=l;i<=len;i++) a[i]=0; len=l;}
cirno operator + (const cirno &u) const {
cirno re(max(len,u.len)); int i;
for(i=0;i<re.len;i++) {
re.a[i]=((i<len?a[i]:0)+(i<u.len?u.a[i]:0))%mod;
}return re;
}
cirno operator - (const cirno &u) const {
cirno re(len); int i;
for(i=0;i<len;i++) {
if(i>=u.len)re.a[i]=a[i];
else re.a[i]=(a[i]-u.a[i]+mod)%mod;
}return re;
}
cirno operator * (const cirno &u) const {
cirno re(len+u.len-1);
int i,j,l=1;
if(re.len<=200) {
for(i=0;i<len;i++) if(a[i]) for(j=0;j<u.len;j++) re.a[i+j]=(re.a[i+j]+ll(a[i])*u.a[j])%mod;
return re;
}
while(l<(len+u.len)) l<<=1;
memset(A,0,l<<2);
memset(B,0,l<<2);
memcpy(A,a,len<<2);
memcpy(B,u.a,u.len<<2);
ntt(A,l,1),ntt(B,l,1);
for(i=0;i<l;i++) A[i]=ll(A[i])*B[i]%mod;
ntt(A,l,-1);
memcpy(re.a,A,re.len<<2);
return re;
}
cirno Get_dao() {
cirno re(len-1); int i;
for(i=1;i<len;i++) re.a[i-1]=ll(i)*a[i]%mod; return re;
}
cirno Get_jifen() {
cirno re(len+1); int i;
for(i=1;i<len;i++) re.a[i]=ll(inv[i])*a[i-1]%mod; return re;
}
cirno Get_inv(int l) const {
cirno re(l); get_inv(a,re.a,l,len); return re;
}
cirno Get_root(int l) const {
cirno re(l); get_root(a,re.a,l,len); return re;
}
cirno Get_ln(int l) const {
cirno re(l); get_ln(a,re.a,l,len); return re;
}
cirno Get_exp(int l) const {
cirno re(l); get_exp(a,re.a,l,len); return re;
}
cirno Get_pow(int k,int l) const {
cirno u=Get_ln(l);
int i;
for(i=0;i<l;i++) u.a[i]=ll(u.a[i])*k%mod;
cirno re=u.Get_exp(l);
return re;
}
cirno operator / (cirno u) {
int n=len,m=u.len,l=1;
while(l<(n-m+1))l<<=1;
rev(),u.rev();
cirno v=u.Get_inv(l);
v.get_mod(n-m+1);
cirno re=(*this)*v;
rev(),u.rev();
re.get_mod(n-m+1);
re.rev();
return re;
}
cirno operator % (cirno u) {
cirno re=*this-u*(*this/u);
re.get_mod(u.len-1);
return re;
}
}tr[N<<2];
char pbuf[2000000],*pp=pbuf;
void write(int x) {
static int sta[20],tp=0;
do {sta[++tp]=x%10,x/=10;}while(x);
while(tp)*pp++=sta[tp--]+'0';
*pp++=' ';
}
void get_inv(int *a,int *b,int len,int la) {
if(len==1) {b[0]=qp(a[0]); return ;}
get_inv(a,b,len>>1,la);
int l=len<<1,i;
memset(A,0,l<<2);
memset(B,0,l<<2);
memcpy(A,a,min(len,la)<<2);
memcpy(B,b,len<<2);
ntt(A,l,1),ntt(B,l,1);
for(i=0;i<l;i++) A[i]=B[i]*(mod+2-ll(A[i])*B[i]%mod)%mod;
ntt(A,l,-1);
memcpy(b,A,len<<2);
}
void get_root(int *a,int *b,int len,int la) {
if(len==1) {b[0]=Sqrt(a[0]); return ;}
get_root(a,b,len>>1,la);
int l=len<<1,i;
memset(C,0,l<<2);
memset(D,0,l<<2);
memset(E,0,l<<2);
memcpy(C,a,min(len,la)<<2);
memcpy(D,b,len<<2);
get_inv(b,E,len,len);
ntt(C,l,1),ntt(D,l,1),ntt(E,l,1);
for(i=0;i<l;i++) C[i]=(ll(C[i])*E[i]+D[i])%mod*inv2%mod;
ntt(C,l,-1);
memcpy(b,C,len<<2);
}
void get_dao(int *a,int *b,int len) {
int i; for(i=1;i<len;i++) b[i-1]=ll(i)*a[i]%mod; b[len-1]=0;
}
void get_jifen(int *a,int *b,int len) {
int i; for(i=1;i<len;i++) b[i]=ll(inv[i])*a[i-1]%mod; b[0]=0;
}
void get_ln(int *a,int *b,int len,int la) {
int l=len<<1,i;
memset(F,0,l<<2);
memset(G,0,l<<2);
get_dao(a,F,min(len,la));
get_inv(a,G,len,la);
ntt(F,l,1),ntt(G,l,1);
for(i=0;i<l;i++) F[i]=ll(F[i])*G[i]%mod;
ntt(F,l,-1);
get_jifen(F,b,len);
}
void get_exp(int *a,int *b,int len,int la) {
if(len==1) {b[0]=1; return ;}
get_exp(a,b,len>>1,la);
int l=len<<1,i;
memset(C,0,l<<2);
memset(D,0,l<<2);
memcpy(C,b,len<<2);
get_ln(b,D,len,len);
for(i=0;i<len;i++) D[i]=(i<la?a[i]:0)-D[i];
D[0]++;
ntt(C,l,1),ntt(D,l,1);
for(i=0;i<l;i++) C[i]=ll(C[i])*D[i]%mod;
ntt(C,l,-1);
memcpy(b,C,len<<2);
}
#define ls p<<1
#define rs p<<1|1
void build(int l,int r,int p,int *px) {
if(l==r) {
tr[p].fix(2);
tr[p].a[0]=mod-px[l];
tr[p].a[1]=1;
return ;
}
int mid=(l+r)>>1;
build(l,mid,ls,px),build(mid+1,r,rs,px);
tr[p]=tr[ls]*tr[rs];
}
void get_val(cirno F,int l,int r,int p,int *px,int *re) {
if(F.len<=450) {
int i,j,t;
for(i=l;i<=r;i++) {
ull tmp=0;
for(j=0,t=1;j<F.len;j++,t=ll(t)*px[i]%mod) {
tmp=(tmp+ll(t)*F.a[j])%mod;
if(!(j&7))tmp%=mod;
}
re[i]=tmp%mod;
}return ;
}
int mid=(l+r)>>1;
get_val(F%tr[ls],l,mid,ls,px,re);
get_val(F%tr[rs],mid+1,r,rs,px,re);
}
cirno solve_polate(int l,int r,int p,int *tmp) {
if(l==r) {
cirno re(1); re.a[0]=tmp[l]; return re;
}
int mid=(l+r)>>1;
cirno L=solve_polate(l,mid,ls,tmp);
cirno R=solve_polate(mid+1,r,rs,tmp);
return L*tr[rs]+R*tr[ls];
}
void Evaluate(int *px,int *re,cirno F,int m) {
build(1,m,1,px);
get_val(F,1,m,1,px,re);
}
cirno Interpolate(int *px,int *py,int n) {
int i;
build(1,n,1,px);
cirno a=tr[1].Get_dao();
static int t[N];
get_val(a,1,n,1,px,t);
for(i=1;i<=n;i++) t[i]=ll(qp(t[i]))*py[i]%mod;
return solve_polate(1,n,1,t);
}
int main() {
//LOJ 150
int n,K,l=1;
n=rd()+1; K=rd();
while(l<n)l<<=1;
ntt_init(l<<1);
int i;
cirno a(n);
for(i=0;i<n;i++) a.a[i]=rd();
cirno b=a.Get_root(l);
cirno c=b.Get_inv(l);
cirno d=c.Get_jifen();
cirno e=d.Get_exp(l);
for(i=0;i<l;i++) e.a[i]=-e.a[i];
for(i=0;i<n;i++) e.a[i]=(e.a[i]+a.a[i])%mod;
e.a[0]+=2, e.a[0]=(e.a[0]-a.a[0])%mod;
cirno f=e.Get_ln(l);
f.a[0]++;
cirno g=f.Get_pow(K,l);
cirno ans=g.Get_dao();
for(i=0;i<n-1;i++) write((ans.a[i]+mod)%mod);
fwrite(pbuf,1,pp-pbuf,stdout);
//Luogu qiuzhi
/*int n,m;
n=rd(),m=rd();
int i,l=1;
while(l<=(n+n))l<<=1;
ntt_init(l);
cirno a(n+1);
static int px[N],ans[N];
for(i=0;i<=n;i++) a.a[i]=rd();
for(i=1;i<=m;i++) px[i]=rd();
Evaluate(px,ans,a,m);
for(i=1;i<=m;i++)printf("%d
",ans[i]);*/
//Luogu chazhi
/*int n,i,l=1;
n=rd();
static int px[N],py[N];
while(l<=(n+n))l<<=1;
ntt_init(l);
for(i=1;i<=n;i++)px[i]=rd(),py[i]=rd();
cirno a=Interpolate(px,py,n);
for(i=0;i<n;i++)printf("%d ",a.a[i]);*/
}
多项式的复合
(A(B(x)))
多项式的复合逆
(F(x),G(x)),(F(G(x))=x) 称(F(x))和(G(x))互为复合逆。
拉格朗日反演
若(F(x))是(G(x))的复合逆,那么满足([x^n]F(x)=frac{1}{n}[x^{n-1}](frac{x}{G(x)})^n)
推广形式:([x^n]H(F(x))=frac{1}{n}[x^{n-1}]H'(x)(frac{x}{G(x)})^n)
特征多项式
https://www.luogu.org/blog/ShadowassIIXVIIIIV/solution-p4723
https://blog.csdn.net/qq_35649707/article/details/78688235
对于懒得推式子选手可以选择记结论:
(A^n=sumlimits_{i=0}^{k-1}c_iA^i)
(St imes A^n=sumlimits_{i=0}^{k-1}c_iSt imes A^i)
(ans=[0](St imes A^n)=sumlimits_{i=0}^{k-1}c_i[0](St imes A^i))
(ans=sumlimits_{i=0}^{k-1}c_iSt_i)
(A^n=Q(A)G(A)+sumlimits_{i=0}^{k-1}c_iA^i)
(g_{k-i}=-a_i)
乘法和取模可以(O(k^2))或(O(klog k))实现。
生成函数
https://www.luogu.org/blog/ShadowassIIXVIIIIV/sheng-cheng-han-shuo-xia-chui
一般生成函数(OGF)
给定一个形如(x_1+x_2+…+x_m=n)的方程,求非负整数解的数量,其中(x_i)满足:(x_1)必须是个偶数(x_2)必须是个质数(x_3)的(μ)值不能为(0),(x_4)必须是一个windy数
指数生成函数(EGF)
给定一些红球、黄球、蓝球和绿球,将其组成一个长度为(n)的序列,要求:红球必须有偶数个,白球数量必须是个质数,蓝球数量的(μ)值不能为(0),绿球数量必须是个windy数
- 可以看出EGF可以用来解决排列问题。
集合的指数生成函数
给定(n)个彼此不同的小球,要求划分为一些集合,每个集合的生成函数是(F(x)),求方案数
- 划分成(i)个集合的方案数为(frac{F^i(x)}{i!}),故总方案数为(sumlimits_{i=0}^{infty}frac{F^i(x)}{i!}=e^{F(x)})
一些可以背一背的生成函数
树:(A(x)=sum_{nge 0}frac{n^{n-2}}{n!}x^n)
森林:(expA(x))
无向图:(C(x)=sum_{nge 0}frac{2^{inom{n}{2}}}{n!}x^n)
无向连通图(lnC(x))
FWT
or卷积和and卷积很好理解
xor卷积看这个https://blog.csdn.net/neither_nor/article/details/60335099
m进制卷积
这个对于or和and还是一个前缀和的性质。
对于xor..可以在模意义下用单位根构造,逆操作可以直接对矩阵求逆。
快速子集变换
大概就是求这么一个式子(A_i=sumlimits_{j+k=i,j&k=0}B_j imes C_k)
用占位多项式搞一搞即可,多开一维数组存(1)的个数,背包合并。
组合数学
第一类斯特林数
(egin{bmatrix} n\ k end{bmatrix}) 表示将(n)个不同元素分成(k)个不同环的方案数,当且仅当两个环不可通过旋转得到时,则两个环不相同。
-
(egin{bmatrix} 0\ 0 end{bmatrix}=1,egin{bmatrix} n\ k end{bmatrix}=egin{bmatrix} n-1\ k-1 end{bmatrix}+egin{bmatrix} n-1\ k end{bmatrix} imes (n-1)) (可能独立成环也可以接到前面某个数的后面。)
-
(sumlimits_{k=0}^negin{bmatrix} n\ k end{bmatrix}=n!) ((egin{bmatrix} n\ k end{bmatrix})恰好是(n)个元素包含(k)个轮换的排列个数)
-
(x^{overline n}=sum_{k}egin{bmatrix}n\ kend{bmatrix}x^k) (证明直接带递推式子进去就行,当然也可以用这个式子来定义斯特林数)
-
(x^{underline n}=sum_{k}egin{bmatrix}n\ kend{bmatrix}(-1)^{n-k}x^k) (这里的(egin{bmatrix}n\ kend{bmatrix}(-1)^{n-k})其实就是有符号第一类斯特林数了)
求一行第一类斯特林数:
由2式能直接得出一个(O(nlog n^2))的做法,这里说一下(O(nlog n))的做法。
分治,假设我们已经求出来(x^{overline n}),如何求出(x^{overline 2n})或(x^{overline {n+1}}) 。
对于后者,可以直接(O(n))乘一下,对于前者,相当于要求(x^{overline n} imes (x+n)^{overline n})
设(f(x)=sumlimits_{i=0}^{n}f_ix^i,g(x)=sumlimits_{i=0}^{n}g_ix_i),分别是上式左右的生成函数。
(g(x)=sumlimits_{i=0}^nf_i(x+n)^i)
(g(x)=sumlimits_{i=0}^nf_isumlimits_{j=0}^jx^jn^{i-j}inom{i}{j})
(g(x)=sumlimits_{j=0}^nfrac{x^j}{j!}sumlimits_{i=j}^nf_ii!frac{n^{i-j}}{(i-j)!})
卷积形式,直接(O(nlog n))乘一下。
总的时间复杂度还是(O(nlog n))的。
第二类斯特林数
(egin{Bmatrix}n\ kend{Bmatrix})表示将n个元素分成k个非空集合的方案数,集合内是无序数。
-
(egin{Bmatrix}n\ kend{Bmatrix}=egin{Bmatrix}n-1\k-1end{Bmatrix}+k imes egin{Bmatrix} n-1\ k end{Bmatrix})
-
(x^n=sum_kegin{Bmatrix}n\ kend{Bmatrix}x^{underline k}) (展开可证,组合意义即(x)种颜色的球选(n)次(=)枚举一共选了(k)种颜色划分的方案数乘从(x)中颜色选出(k)个进行排列的方案数)
-
(x^n=sum_kegin{Bmatrix}n\ kend{Bmatrix}(-1)^{n-k}x^{overline k})
-
(egin{Bmatrix}n\kend{Bmatrix}=frac{1}{k!}sumlimits_{i=0}^k(-1)^iinom{i}{k}(k-i)^n) (就是令集合间有序,然后枚举有几个集合是空的进行容斥)
求一行第二类斯特林数:
- 完全可以用第3个式子直接做了,复杂度(O(nlog n))。
斯特林反演
可以把第一类的1式,第二类的1,2式合起来,得到(sumlimits_{k=p}^negin{Bmatrix}n\kend{Bmatrix}egin{bmatrix}k\pend{bmatrix}(-1)^{n-k}=[p=n]),然后就可以愉快的进行反演,得
单位根反演
https://blog.csdn.net/DT_Kang/article/details/79944113
(frac{1}{n}sumlimits_{i=0}^{n-1}w^{ki}=[n|k])
怎么求原根
从(2)开始枚举(g),检查是否对于所有的(q,is[q],q|varphi(p))都满足(g^{frac{phi}{q}} ot =1) 。
置换
https://blog.csdn.net/zhouyuheng2003/article/details/88527913
广义二项式定理
((1+x)^{-n}=sumlimits_{i=0}^{infty}(-1)^{i}inom{n+i-1}{i})
((1-x)^{-n}=sumlimits_{i=0}^{ninfty}inom{n+i-1}{i})