Siyao模板库Word文件下载.docx
《Siyao模板库Word文件下载.docx》由会员分享,可在线阅读,更多相关《Siyao模板库Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。
![Siyao模板库Word文件下载.docx](https://file1.bdocx.com/fileroot1/2023-1/21/f167d378-10d0-4834-a7f3-43c6b4eeca24/f167d378-10d0-4834-a7f3-43c6b4eeca241.gif)
24、n!
n!
/n!
多阶乘乘除模k(k为square-free数)9
25、n!
(con)&
invmodk阶乘与k互素部分ff以及逆元fv打表已经测试FZU18339
26、sum_mod等比数列求和取模10
27、floor,ceil高斯函数:
取上下整已经测试SGU10610
28、一次不等式求整数解:
L=<
ax+b<
=R已经测试SGU10610
29、二元一次方程求整数解对:
ax+by+c=0xl=<
x<
=xryl<
=y<
=yr已经测试SGU10610
30、素数测试之miller-rabin:
返回false则一定是合数已经测试PKU181110
31、素数测试函数:
isprime(n)11
32、Pollard-rho算法对合数找到一个因数已经测试PKU181111
33、分解为素因子的积:
利用Pollard-rho算法(n为1特殊处理了)12
34、Farey逼近分数:
得到分母<
n中与目标分数最接近分数已测试ECNU264912
35、Pell方程:
x^2-dy^2=1的解12
36、带限制可重排列:
13
NumberTheroy
避免乘法溢出
typedef__int64ll;
typedefconst__int64cll;
llmul_mod(lla,llb,cll&
n){//二进制思想已经测试PKU1811
llans(0),tmp((a%n+n)%n);
b=(b%n+n)%n;
//b%=n;
while(b){
if(b&
1)if((ans+=tmp)>
=n)ans-=n;
if((tmp<
<
=1)>
=n)tmp-=n;
b>
>
=1;
}returnans;
}
求两数最大公约数已经测试
欧几里得算法.适用非负整数.效率:
o(logn).
llgcd(lla,llb){
if(!
a)returnb;
if(!
b)returna;
while(a>
b?
a%=b:
b%=a);
returna+b;
llgcd(lla,llb){return(b==0?
a:
gcd(b,a%b));
}
llgcd(lla,llb){if(b)while(b^=a^=b^=a%=b);
returna;
二进制算法.避免了模运算.大整数时效率较高.o(logn)
llgcd(lla,llb){
(a&
1)&
&
!
(b&
1))returngcd(a>
1,b>
1)<
1;
elseif(!
1))returngcd(a,b>
1);
1))returngcd(a>
1,b);
elseif(a<
b)returngcd(b-a,a);
elsereturngcd(a-b,b);
voidgcd(lla,llb,ll&
d,ll&
x,ll&
y){//已经测试FZU1402
b){d=a;
x=1;
y=0;
else{gcd(b,a%b,d,y,x);
y-=a/b*x;
4、CF_GCD连分数方法解ax=gcd(a,b)mod(b)以及ax+by=gcd(a,b)=d.
a/b=<
a0,……,an>
ak[n-1]-bh[n-1]=(-1)^(n+1)gcd(a,b)
h[-2]=0,h[-1]=1,k[-2]=1,k[-1]=0;
llcfgcd(lla,llb){//getxofax=d(modb)已经测试FZU1402
intc[40],l=0;
llx1=0,x=1,p=b;
while(b){c[l++]=a/b;
a%=b;
a^=b^=a^=b;
for(inti=0;
i<
l;
++i,swap(x1,x))x=(x1*c[i]+x)%p;
//控制溢出
returnl&
1?
p-x:
x;
y){x=cfgcd(a,b);
d=a*x%b;
d)d=b;
y=(a*x-d)/b;
解ax=b(modn).
不定方程:
ax+by=c特解为x0=x*c/d,y0=y*c/d通解x=x0+b/d*t,y=y0-a/d*t
也就是解ax+ny=b的x的通解对模n的剩余系。
答案在c[]数组中。
llmsolve(lla,llb,lln,llc[]){//besuren>
0返回剩余系的个数
lld,x,y;
gcd(a,n,d,x,y);
if(b%d)return0;
for(x=((b/d)*x)%(n/d),i=0;
d;
++i,x+=n/d)c[i]=x;
returnd;
b=1时x为a的逆元
llinv(lla,lln){//无逆元返回-1
returnd==1?
(x%n+n)%(n/d):
-1;
返回a^nmodp
乘法部分需要自己写mul_mod(a,b,p)(a*b%p)避免溢出。
效率o(logn)。
llpow_mod(lla,lln,llp){
llans
(1),d(a%p);
while(n){
if(n&
1)ans=mul_mod(ans,d,p);
//ans=((longlong)ans*d)%p;
d=mul_mod(d,d,p);
//d=((longlong)d*d)%p;
n>
returnans;
返回是否有解,解为x=m(moda)已经测试FZU1402
boolcombm(ll&
a1,ll&
m1,lla2,llm2){//k1m1+a1=k2m2+a2=>
k1m1-k2m2=a2-a1
lld,x,y,m,a;
gcd(m1,m2,d,x,y);
if((a2-a1)%d)returnfalse;
//while(a1%m2!
=a2)a1+=m1;
m1*=m2/d;
returntrue;
//暴力也可以
m2/=d;
x=(x%m2)*((a2-a1)/d%m2)%m2;
//小心溢出
a1=x*m1+a1;
m1*=m2;
a1=(a1%m1+m1)%m1;
得到x=x0(modb1……bn)
llchina(lla[],llb[],intn){//解同余方程已经测试FZU1402
lltmp=1,x,y,d,ans=0;
n;
++i)tmp*=b[i];
++i){
gcd(tmp/b[i],b[i],d,x,y);
ans=(ans+tmp/b[i]*x*a[i])%tmp;
}
return(ans+tmp)%tmp;
llchina(lla[],llb[],intn){//试除已经测试FZU1402
llans=a[0]%b[0],tmp=b[0];
for(inti=1;
tmp*=b[i++])while(ans%b[i]!
=a[i])ans=ans+tmp;
returnans%tmp;
不停合并两方程
boolg_solve(lla[],llb[],intn,ll&
ans,ll&
mod){//返回是否有解已经测试FZU1402
ans=a[0]%b[0],mod=b[0];
++i)if(!
combm(ans,mod,a[i],b[i]))returnfalse;
returntrue;
//for(inti=0;
++i)if((ans-a[0])%b[0])while
(1);
返回满足a^x=b(modn)的最小解,无解返回-1
structnode{
llv;
llpos;
}mmap[MAX];
intsize=0;
booloperator<
(nodea,nodeb){returna.v<
b.v||a.v==b.v&
a.pos<
b.pos;
voidinsert(llv,intpos){
mmap[size].v=v;
mmap[size].pos=pos;
++size;
return;
intbsearch(lla){
intlow=-1,high=size-1;
while(low+1<
high)
{
intmid=(low+high)/2;
if(mmap[mid].v<
a)
low=mid;
else
high=mid;
if(mmap[high].v!
=a)return-1;
returnmmap[high].pos;
lllog(lla,llb,lln){//Baby-Step-Giant-Step,nisprime
intm=(int)ceil(sqrt(n*1.0));
intv=inv(pow_mod(a,m,n),n);
insert(1%n,size=0);
inte=1,i,k;
for(i=1;
m;
insert(e,i++))e=mul_mod(e,a,n);
//e=((longlong)e*a)%n;
sort(mmap,mmap+size);
for(i=0;
b=mul_mod(b,v,n),++i)//b=((longlong)b*v)%n;
if((k=bsearch(b))!
=-1)returni*m+k;
return-1;
intprim[]中保存素数,pnum保存个数,hash可以用bool型
constintprimN=31650;
//sqrt(10^9)//已经测试FZU1402
intp[primN],hash[primN],pnum=0;
voidmlist(){
p[pnum++]=2;
for(inti=3;
primN;
i+=2)
hash[i]){
p[pnum++]=i;
if(i<
10000)for(intj=i*i;
j<
j+=i+i)hash[j]=1;
//小心j溢出
}
intpf[]中保存素因子intlim[]保存幂次,pfnum保存个数
intpf[60],pfnum=0,lim[60];
//已经测试FZU1402
voidpfact(intn){
pfnum=0;
for(inti=0;
pnum&
p[i]*p[i]<
=n;
++i)
if(n%p[i]==0){
lim[pfnum]=0;
while(n%p[i]==0)n/=p[i],++lim[pfnum];
pf[pfnum++]=p[i];
if(n!
=1)lim[pfnum]=1,pf[pfnum++]=n;
phis求1-n所有数的phi
llphi(lln){//已经测试FZU1759
llans=n,i,j=4;
for(inti=2;
j+=i+i+1,++i)
if(n%i==0){
ans=ans/i*(i-1);
while(n%i==0)n/=i;
=1)ans=ans/n*(n-1);
llphi(lln){//需要素数表已经测试FZU1759
llans=n;
(longlong)p[i]*p[i]<
++i){//小心乘溢出
ans=ans/p[i]*(p[i]-1);
while(n%p[i]==0)n/=p[i];
constintphiN=1000001;
//已经测试HDU1645TJU3317
intphi[phiN];
voidphis(){
phiN;
++i)phi[i]=i;
for(inti=2;
if(phi[i]==i)
for(intj=i;
j+=i)phi[j]=phi[j]/i*(i-1);
14、square_free()拟筛法生成Square-free数:
intsf[]中存结果,shh[]中存因子数(以便进行容斥)
constintSFN=100001;
//已测试TJU3317
intsf[SFN],shh[SFN],sfnum=0;
voidsquare_free(){
sfnum=shh[1]=0,sf[sfnum++]=1;
SFN;
shh[i])for(intj=i;
j+=i)if(shh[j]!
=-1)(j/i)%i==0?
shh[j]=-1:
++shh[j];
if(shh[i]!
=-1)sf[sfnum++]=i;
m元组最大公约数为1已经测试TJU3121
constintnpN=10001;
intnphh[npN];
llnpairco(inta[],intn,intm){
inti,j,ma,m1,tmp;
llans(0);
for(i=0;
npN;
++i)nphh[i]=0;
//清空hash
for(ma=i=0;
++i){
++nphh[a[i]];
if(a[i]>
ma)ma=a[i];
m1=ma/m;
for(ans=i=0;
sfnum&
sf[i]<
=m1;
++i){//计算sf[i]的倍数有多少
for(tmp=0,j=sf[i];
=ma;
j+=sf[i])tmp+=nphh[j];
if(tmp>
=m)ans+=(shh[sf[i]]&
1)?
-c(tmp,m):
c(tmp,m);
//c(n,k)为组合数
returnans;
求[1,r]区间中与x互质的数的个数已经测试TJU3317
voiddfs(intstep,boolflag,intv,constint&
R,int&
ans){
if(v>
R)return;
if(step>
=pfnum){
if(v!
=1)ans+=flag?
(R/v):
-(R/v);
else{
dfs(step+1,flag,v,R,ans);
if((ll)v*pf[step]<
=R)dfs(step+1,1^flag,v*pf[step],R,ans);
intlineco(intr,intx){//[1,r]中与x互质的个数
pfact(x);
//分解x
intans=(r/x)*phi[x]+r%x;
dfs(0,1,1,r%=x,ans);
//欧拉函数加速
//intans=r;
dfs(0,1,1,r,ans);
//用这个事先不需要生成phi
求[1,x],[1,y]互质的对数
有序对:
//已经测试TJU3317
llgridco(lln,llm){
if(n>
m)swap(n,m);
llret=0;
ret+=shh[sf[i]]&
1?
-(n/sf[i])*(m/sf[i]):
(n/sf[i])*(m/sf[i]);
//小心溢出
returnret;
无序对:
gridco(n,m)-(gridco(n,n)-1)/2(n<
m)//已经测试HDU1695
求[1,x],[1,y]互质的对数
枚举小区间中的数调用lineco已经测试TJU3317
llgridco(intn,intm){//[1,m]与[1,n]中互质的数对(a,b)!
=(b,a)
m)swap(n,m);
for(inti=1;
++i)ret+=lineco(m,i);
枚举小区间中的数调用lineco减去重复对(注意把1多减的加回)已经测试HDU1695
n)return0;
//phi[1]=0;
++i)ret+=lineco(m,i)-phi[i];
returnret+1;
已经测试HDU2588
pfact(n);
//分解ans=0;
//初始化dfs(0,1,1);
//调用
voiddfs(intstep,intv,intphi){
=pfnum);
//相应处理
else{
dfs(step+1,v,phi);
v*=pf[step],phi*=pf[step]-1;
=lim[step];
v*=pf[step],phi*=pf[step];
已经测试POJ2720TJU3313
a^b(modn)=a^(b>
phi(n)?
b%phi(n)+phi(n):
b)(modn)
intflag=0;
intget(intb,inti,intn)//f(i)%n=b^(f(i-1)%phi(n))POJ2720
{
if(b==1||i==0)return1%n;
//出口
intt=get(b,i-1,phi(n));
//返回f(i-1)%phi(n)
if(flag)t+=phi(n);
longlongtmp=b,ans=1;
//要注意如果基数小(0或者1)可能要把flag值变回0
while(t){
if(t&
1){
ans=ans*tmp;
if(ans>
=n)ans%=n,flag=1;
tmp=tmp*tmp;
if(tmp>
=n)tmp%=n,flag=1;
t>
intget(inti,intn)//f(i)%n=(i%10)^(f(i/10)%phi(n))TJU3313
if(i==0)return1%n;