ACM数学模板.docx

上传人:b****6 文档编号:8111483 上传时间:2023-01-28 格式:DOCX 页数:20 大小:81.15KB
下载 相关 举报
ACM数学模板.docx_第1页
第1页 / 共20页
ACM数学模板.docx_第2页
第2页 / 共20页
ACM数学模板.docx_第3页
第3页 / 共20页
ACM数学模板.docx_第4页
第4页 / 共20页
ACM数学模板.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

ACM数学模板.docx

《ACM数学模板.docx》由会员分享,可在线阅读,更多相关《ACM数学模板.docx(20页珍藏版)》请在冰豆网上搜索。

ACM数学模板.docx

ACM数学模板

2.扩展欧几里得(求ax+by=gcd(a,b)的特解)

voide_gcd(LLa,LLb,LL&d,LL&x,LL&y){

if(b==0){

x=1;y=0;d=a;

}

else{

e_gcd(b,a%b,d,y,x);

y-=x*(a/b);

}

}

3.中国剩余定理

同余方程组

x ≡a1(modm1)

x ≡a2(modm2)

......

x ≡ak(modmk)

方程组所有的解的集合就是:

x1=N1*a1+N2*a2+...+Nk*ak

 

其中Nimodmi=1,Ni=ai*ti,可用欧几里得扩展定理求ti.其中M=m1*m2*m3····*mn;

//互质版

  #include

usingnamespacestd;

//参数可为负数的扩展欧几里德定理

voidexOJLD(inta,intb,int&x,int&y){

//根据欧几里德定理

if(b==0){//任意数与0的最大公约数为其本身。

x=1;

y=0;

}else{

intx1,y1;

exOJLD(b,a%b,x1,y1);

if(a*b<0){//异号取反

x=-y1;

y=a/b*y1-x1;

}else{//同号

x=y1;

y=x1-a/b*y1;

}

}

}

//剩余定理

intcalSYDL(inta[],intm[],intk){

intN[k];//这个可以删除

intmm=1;//最小公倍数

intresult=0;

for(inti=0;i

mm*=m[i];

}

for(intj=0;j

intL,J;

exOJLD(mm/m[j],-m[j],L,J);

N[j]=m[j]*J+1;//1

N[j]=mm/m[j]*L;//2【注】1和2这两个值应该是相等的。

result+=N[j]*a[j];

}

return(result%mm+mm)%mm;//落在(0,mm)之间,这么写是为了防止result初始为负数,本例中不可能为负可以直接写成:

returnresult%mm;即可。

}

intmain(){

inta[3]={2,3,2};

intm[3]={3,5,7};

cout<<"结果:

"<

}

  //不互质版

     /**

   中国剩余定理(不互质)

   */ 

   #include 

   #include 

   #include 

   usingnamespacestd; 

   typedeflonglongLL; 

   LLMod; 

     

   LLgcd(LLa,LLb) 

   { 

       if(b==0) 

           returna; 

       returngcd(b,a%b); 

   } 

     

   LLExtend_Euclid(LLa,LLb,LL&x,LL&y) 

   { 

       if(b==0) 

       { 

           x=1,y=0; 

           returna; 

       } 

       LLd=Extend_Euclid(b,a%b,x,y); 

       LLt=x; 

       x=y; 

       y=t-a/b*y; 

       returnd; 

   } 

     

   //a在模n乘法下的逆元,没有则返回-1 

   LLinv(LLa,LLn) 

   { 

       LLx,y; 

       LLt=Extend_Euclid(a,n,x,y); 

       if(t!

=1) 

           return-1; 

       return(x%n+n)%n; 

   } 

     

   //将两个方程合并为一个 

   boolmerge(LLa1,LLn1,LLa2,LLn2,LL&a3,LL&n3) 

   { 

       LLd=gcd(n1,n2); 

       LLc=a2-a1; 

       if(c%d) 

           returnfalse; 

       c=(c%n2+n2)%n2; 

       c/=d; 

       n1/=d; 

       n2/=d; 

       c*=inv(n1,n2); 

       c%=n2; 

       c*=n1*d; 

       c+=a1; 

       n3=n1*n2*d; 

       a3=(c%n3+n3)%n3; 

       returntrue; 

   } 

     

   //求模线性方程组x=ai(modni),ni可以不互质 

   LLChina_Reminder2(intlen,LL*a,LL*n) 

   { 

       LLa1=a[0],n1=n[0]; 

       LLa2,n2; 

       for(inti=1;i

       { 

           LLaa,nn; 

           a2=a[i],n2=n[i]; 

           if(!

merge(a1,n1,a2,n2,aa,nn)) 

               return-1; 

           a1=aa; 

           n1=nn; 

       } 

       Mod=n1; 

       return(a1%n1+n1)%n1; 

   } 

   LLa[1000],b[1000]; 

   intmain() 

   { 

       inti; 

       intk; 

       while(scanf("%d",&k)!

=EOF) 

       { 

           for(i=0;i

               scanf("%I64d%I64d",&a[i],&b[i]); 

           printf("%I64d\n",China_Reminder2(k,b,a)); 

       } 

       return0; 

   } 

 

4.欧拉函数(求一个数前面的所有与这个数互质的数的个数)

 Euler函数表达通式:

euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。

euler

(1)=1(唯一和1互质的数就是1本身)。

 

Euler函数有几个性质:

  1.如果q,p互质,则Euler(p*q)=Euler(p)*Euler(q);

  2.如果a=p^k,则Euler(a)=p^k-p^k-1;

//直接求解欧拉函数

inteuler(intn){//返回euler(n)

intres=n,a=n;

for(inti=2;i*i<=a;i++){

if(a%i==0){

res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出

while(a%i==0)a/=i;

}

}

if(a>1)res=res/a*(a-1);

returnres;

}

//线性筛选欧拉函数O(n)用到了一下性质:

//

(1)若(N%a==0&&(N/a)%a==0)则有:

E(N)=E(N/a)*a;

//

(2)若(N%a==0&&(N/a)%a!

=0)则有:

E(N)=E(N/a)*(a-1);

//注意:

如果范围过大可能不适宜开数组来做

   inteuler[maxN],vis[maxN],prime[maxN/5],e[maxN],cnt=0;

   voidmake_euler(){

      memset(vis,0,sizeof(vis));

      euler[1]=1;

      for(inti=2;i

         if(vis[i]==0){

            prime[cnt++]=i;

            euler[i]=i-1;

         }

         for(intj=0;j

            vis[i*prime[j]]=1;

            if(i%prime[j]==0){

               euler[i*prime[j]]=euler[i]*prime[j];

               break;

            }

            elseeuler[i*prime[j]]=euler[i]*(prime[j]-1);

         }

      }

   }

   

 

 5.求N以前N的约数个数

  约数个数的性质,对于一个数N,N=p1^a1+p2^a2+...+pn^an。

其中p1,p2,p3...pn是N的质因数,a1,a2,a2,...an为相应的指数,则

                                                          div_num[N]=(p1+1)*(p2+1)*(p3+1)*...*(pn+1);

结合这个算法的特点,在程序中如下运用:

 对于div_num:

(1)如果i|prime[j]那么div_num[i*prime[j]]=div_sum[i]/(e[i]+1)*(e[i]+2)                 //最小素因子次数加1

(2)否则div_num[i*prime[j]]=div_num[i]*div_num[prime[j]]                                    //满足积性函数条件

 对于e:

(1)如果i|pr[j] e[i*pr[j]]=e[i]+1;//最小素因子次数加1

(2)否则e[i*pr[j]]=1;             //pr[j]为1次

 

#include

#include

#defineM100000

usingnamespacestd;

intprime[M/3],e[M],div_num[M];//e[i]表示第i个素数因子的个数

boolflag[M];

voidget_prime()

{

inti,j,k;

memset(flag,false,sizeof(flag));

k=0;

for(i=2;i

if(!

flag[i]){

prime[k++]=i;

e[i]=1;

div_num[i]=2;//素数的约数个数为2

}

for(j=0;j

flag[i*prime[j]]=true;

if(i%prime[j]==0){

div_num[i*prime[j]]=div_num[i]/(e[i]+1)*(e[i]+2);

e[i*prime[j]]=e[i]+1;

break;

}

else{

div_num[i*prime[j]]=div_num[i]*div_num[prime[j]];

e[i*prime[j]]=1;

}

}

}

}

 

6.莫比乌斯函数

  一个讲得比较清楚的PPT:

  线性筛打表莫比乌斯函数:

intmob[maxN],vis[maxN],prime[maxN],cnt=0;

voidmake_mobius(){

mob[1]=1;

memset(vis,0,sizeof(vis));

for(inti=2;i

if(!

vis[i]){

mob[i]=-1;

prime[cnt++]=i;

}

for(intj=0;j

vis[i*prime[j]]=1;

if(i%prime[j]==0){

mob[i*prime[j]]=0;

break;

}

elsemob[i*prime[j]]=-mob[i];

}

}

}

7.卢卡斯定理

//卢卡斯定理C(m,n)%p

LLLucas(LLm,LLn,LLp){

LLres=1;

while(n&&m){

LLn1=n%p,m1=m%p;

//费马小定理求逆元

res=res*fac[n1]*qsm(fac[m1]*fac[n1-m1]%p,p-2,p)%p;

//扩展欧几里得求逆元

//res=res*fac[n1]*reverse(fac[m1],p)*reverse(fac[n1-m1],p)%p;

n/=p;

m/=p;

}

return(res%p+p)%p;

}

 

8.卡特兰数

递推公式

9.伯努利数

   伯努利数满足条件

,且有

    

     那么继续得到

    

voidinit_ber(){

ber[0]=1;

for(inti=1;i

LLans=0;

for(intj=0;j

ans=(ans+comb[i+1][j]*ber[j])%mod;

ans=-ans*inv(i+1,mod)%mod;

ber[i]=(ans%mod+mod)%mod;

}

}

10.乘法逆元

因为

可能会很大,超过int范围,所以在快速幂时要二分乘法。

逆元打表(O(n)):

    inv[1] = 1;  

    for(int i=2;i

    {  

        if(i >= MOD) break;  

        inv[i] = (MOD - MOD / i) * inv[MOD % i]% MOD;  

    }  

 

11.millerrabin算法pollardrho算法(概率高效判断素数,求因子)

#include

#include

#include

#include

#include

constintTimes=10;

constintN=5500;

usingnamespacestd;

typedeflonglongLL;

LLct,cnt,c,x,y;

LLfac[N],num[N],arr[N];

LLgcd(LLa,LLb)

{

returnb?

gcd(b,a%b):

a;

}

LLmulti(LLa,LLb,LLm)

{

LLans=0;

while(b)

{

if(b&1)

{

ans=(ans+a)%m;

b--;

}

b>>=1;

a=(a+a)%m;

}

returnans;

}

LLquick_mod(LLa,LLb,LLm)

{

LLans=1;

a%=m;

while(b)

{

if(b&1)

{

ans=multi(ans,a,m);

b--;

}

b>>=1;

a=multi(a,a,m);

}

returnans;

}

boolMiller_Rabin(LLn)

{

if(n==2)returntrue;

if(n<2||!

(n&1))returnfalse;

LLa,m=n-1,x,y;

intk=0;

while((m&1)==0)

{

k++;

m>>=1;

}

for(inti=0;i

{

a=rand()%(n-1)+1;

x=quick_mod(a,m,n);

for(intj=0;j

{

y=multi(x,x,n);

if(y==1&&x!

=1&&x!

=n-1)returnfalse;

x=y;

}

if(y!

=1)returnfalse;

}

returntrue;

}

LLPollard_rho(LLn,LLc)

{

LLx,y,d,i=1,k=2;

y=x=rand()%(n-1)+1;

while(true)

{

i++;

x=(multi(x,x,n)+c)%n;

d=gcd((y-x+n)%n,n);

if(1

if(y==x)returnn;

if(i==k)

{

y=x;

k<<=1;

}

}

}

voidfind(LLn,intc)

{

if(n==1)return;

if(Miller_Rabin(n))

{

fac[ct++]=n;

return;

}

LLp=n;

LLk=c;

while(p>=n)p=Pollard_rho(p,c--);

find(p,k);

find(n/p,k);

}

voiddfs(LLdept,LLproduct=1)

{

if(dept==cnt)

{

arr[c++]=product;

return;

}

for(inti=0;i<=num[dept];i++)

{

dfs(dept+1,product);

product*=fac[dept];

}

}

voidSolve(LLn)

{

ct=0;

find(n,120);

sort(fac,fac+ct);

num[0]=1;

intk=1;

for(inti=1;i

{

if(fac[i]==fac[i-1])

++num[k-1];

else

{

num[k]=1;

fac[k++]=fac[i];

}

}

cnt=k;

}

constintM=1000005;

boolprime[M];

intp[M];

intk1;

voidisprime()

{

k1=0;

inti,j;

memset(prime,true,sizeof(prime));

for(i=2;i

{

if(prime[i])

{

p[k1++]=i;

for(j=i+i;j

{

prime[j]=false;

}

}

}

}

intmain()

{

LLn,t,record,tmp;

isprime();

while(cin>>n)

{

LLans=-1;

record=0;

while(true)

{

tmp=1;

if(Miller_Rabin(n))

{

Solve(n-1);

c=0;

dfs(0,1);

sort(arr,arr+c);

boolflag=0;

for(inti=0;i

{

if(quick_mod(10,arr[i],n)==1)

{

tmp=arr[i];

break;

}

if(i==c-2)flag=1;

}

if(flag)

{

if(ans

cout<

break;

}

}

else

{

boolflag=false;

LLtmp1=(LL)sqrt(n*1.0);

if(tmp1*tmp1==n&&Miller_Rabin(tmp1))

{

x=tmp1;

y=2;

flag=true;

}

else

{

LL

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1