1. 程式人生 > >NOIP模板複習——數論

NOIP模板複習——數論

最大公約數與最小公倍數

int gcd(int a,int b)
{
	int r=a%b;
	while(r!=0)
	{
		a=b;
		b=r;
		r=a%b;
	}
	return b;
}
int lcm(int a,int b)
{
	return a*b/gcd(a,b);
}

快速冪&快速積

快速積的主要作用是防止乘數過大,炸 long long 範圍

int Multiply(int a,int b)
{
	int ans=0;
	while(b)
	{
		if(b&1)
		  ans=(ans+a)%Mod;
		a=(a+a)
%Mod; b>>=1; } return ans; } int Power(int a,int b) { int ans=1; while(b) { if(b&1) ans=Multiply(ans,a); a=Multiply(a,a); b>>=1; } return ans; }

線性篩

p r i m

e prime 是素數集, m a x max 是最大質因數, m
i n min
是最小質因數, p h i phi 是尤拉函式, m a r k mark 是標記一個數是否為素數

int prime[N],Max[N],Min[N],phi[N];
bool mark[N];
void linear_sieves()
{
	int i,j,sum=0;
	memset(mark,true,sizeof(mark));
	mark[0]=mark[1]=false;phi[1]=1;
	for(i=2;i<N;++i)
	{
		if(mark[i])
		{
			phi[i]=i-1;
			prime[++sum]=i;
			Min[i]=Max[i]=i;
		}
		for(j=1;j<=sum&&i*prime[j]<N;++j)
		{
			mark[i*prime[j]]=false;
			Max[i*prime[j]]=Max[i];
			Min[i*prime[j]]=prime[j];
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else  phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}

質因數分解

這個要用到線性篩素數( s u m sum 是篩出的素數個數)

聽說複雜度是 O ( n ln n ) O(\frac{\sqrt n}{\ln n}) (因為 n n 以內的素數約有 n ln n \frac{n}{\ln n} 個,所以 n \sqrt n 內就有 n ln n \frac{\sqrt n}{\ln \sqrt n} 個,而 ln n = 2 ln n \ln n=2\ln \sqrt n ),不過只用記住它比較小就行了

void divide(int x)
{
	int i;
	for(i=1;i<=sum&&prime[i]*prime[i]<=x;++i)
	{
		while(x%prime[i]==0)
		{
			x/=prime[i];
			printf("%d ",prime[i]);
		}
	}
	if(x!=1)  printf("%d",x);
}

擴充套件歐幾里得

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

逆元

快速冪(要求模數必須為質數)

inv 是逆元,x 是要求逆元的數,Power是快速冪,Mod 是模數

inv=Power(x,Mod-2);

擴充套件歐幾里得(要求 x 必須與 Mod 互質)

exgcd(x,Mod,inv,y);
inv=(inv+Mod)%Mod;

Ps:快速冪和擴歐的模板就去上面看啦

線推

inv[1]=1;
for(i=2;i<=n;++i)
    inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod;

組合數

O ( n 2 ) O(n^2) 遞推組合數(方便取模)

C[n][m] 表示 C n m C_{n}^{m}

C[0][0]=1;
for(i=1;i<=n;++i)
{
	C[i][0]=1;
	for(j=1;j<=i;++j)
	    C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod;
}

線性篩出階乘和逆元, O ( 1 ) O(1) 求組合數(Power 是快速冪,求逆元用的)

f a c fac 是階乘, i n v inv 是階乘的逆元

void init()
{
	int i;
	fac[0]=fac[1]=1;
	for(i=2;i<=n;++i)  fac[i]=1ll*fac[i-1]*i%Mod;
	inv[n]=Power(fac[n],Mod-2);
	for(i=n-1;i>=1;--i)  inv[i]=1ll*inv[i+1]*(i+1)%Mod;
}
int C(int n,int m)
{
	return 1ll*fac[n]*inv[m]%Mod*inv[n-m]%Mod;
}

高斯消元

a[i][1]~a[i][n] 是各個元的係數, a[i][n+1] 是該計算出來的值

void Guass()
{
	int i,j,k;
	for(i=1;i<=n;++i)
	{
		k=i;
		for(j=i+1;j<=n;++j)
		  if(fabs(a[k][i])<fabs(a[j][i]))
		    k=j;
		swap(a[i],a[k]);
		for(j=i+1;j<=n;++j)
		  for(k=i+1;k<=n+1;++k)
		    a[j][k]-=a[i][k]*a[j][i]/a[i][i];
	}
	for(i=n;i;--i)
	{
		for(j=i+1;j<=n;++j)
		  a[i][n+1]-=ans[j]*a[i][j];
		ans[i]=a[i][n+1]/a[i][i];
	}
}

矩陣快速冪

這裡就把大致的框架打出來(程式碼中是 2 2 2*2 的矩陣)

struct matrix
{
	int m[N][N];
	matrix(int t=0)
	{
		memset(m,0,sizeof(m));
		for(int i=1;i<=2;++i)  m[i][i]=t;
	}
	friend matrix operator * (const matrix &a,const matrix &b)
	{
		int i,j,k;
		matrix c(0);
		for(i=1;i<=2;++i)
		  for(j=1;j<=2;++j)
		    for(k=1;k<=2;++k)
		      c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
		return c;
	}
	friend matrix operator ^ (matrix a,long long b)
	{
		matrix c(1);
		for(;b;b>>=1,a=a*a)
		  if(b&1)
		    c=c*a;
		return c;
	}
};

康拓展開

康拓展開和逆康拓展開( f a c fac 是預處理出來的階乘)

ll cantor()
{
	ll ans=0;
	for(int i=1;i<=n;++i)
	{
		int num=0;
		for(int j=i+1;j<=n;++j)
		  if(a[j]<a[i])  num++;
		ans+=fac[n-i]*num;
	}
	return ans;
}
void reverse_cantor(ll x)
{
	int i,j;x--;
	memset(vis,false,sizeof(vis));
	for(i=1;i<=n;++i)
	{
		int num=x/fac[n-i
            
           

相關推薦

NOIP模板複習——數論

最大公約數與最小公倍數 int gcd(int a,int b) { int r=a%b; while(r!=0) { a=b; b=r; r=a%b; } return b; } int lcm(int a,int b) { return a*b/gcd(a,b

備戰NOIP——模板複習2

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 並查集模板 路徑壓縮 /*Copyright: Copyright (c) 2018 *Created o

備戰NOIP——模板複習7

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 Tarjan模板 /*Copyright: Copyright (c) 2018 *Created on 2

備戰NOIP——模板複習9

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 最近公共祖先(LCA) 樹鏈剖分 /*Copyright: Copyright (c) 2018 *Cre

備戰NOIP——模板複習13

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 二分圖匹配 匈牙利演算法 /*Copyright: Copyright (c) 2018 *Created

備戰NOIP——模板複習15

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 對頂堆 (動態計算中位數) /*Copyright: Copyright (c) 2018 *Create

備戰NOIP——模板複習18

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 Nim遊戲 /*Copyright: Copyright (c) 2018 *Created on 2018

備戰NOIP——模板複習20

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 線性篩求尤拉函式 /*Copyright: Copyright (c) 2018 *Created on 2

備戰NOIP——模板複習24

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 逆元 費馬小定理 線性遞推 逆元 費馬小定理 /*Copyright: Copyright (c

NOIP模板複習——資料結構

並查集 int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void Merge(int x,int y) { x=find(x); y=find(y);

NOIP模板複習——圖論

由於圖論中有些演算法的程式碼比較長,就只貼核心程式碼 最短路 floyd void floyd() { int i,j,k; for(k=1;k<=n;++k) for(i=1;i<=n;++i) for(j=1;j<=n;++j

NOIP模板複習——經典動態規劃

揹包問題 0/1 揹包 n 為物品數,m 為揹包體積,v 為物品體積,w 為物品價值,f[i] 為體積為 i 的揹包能獲得的最大價值 for(i=1;i<=n;++i) { scanf("%d%d",&v,&w); for(j=m;j>=v;--j

NOIP模板複習——字串

雜湊 直接用 unsigned long long,讓它自然溢位(對 2 64

NOIP模板複習——基礎演算法

二分 求滿足條件的最小值 while(l<r) { int mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } 求滿足條件的最大值 while(l<r) { int mid=(l+r+1

備戰NOIP——模板複習19

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 最小生成樹 Prim /*Copyright: Copyright (c) 2018 *Created o

備戰NOIP——模板複習14

這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。 樹狀陣列(B.I.T) 單點修改區間查詢 /*Copyright: Copyright (c) 2018

NOIP複賽複習(三)檔案讀寫與數論模板

檔案讀入讀出 假設題目名為“add”,那麼資料夾名為“add”,c++程式名為“add.cpp”,讀入檔名為“add.in”,輸出檔名為“add.out”。四個的拼寫均不可有誤,包括大小寫差異。千萬不要除錯後就忘記修改檔案讀入讀出了。  #include<cstdio&

NOIP複賽複習(十二)數論演算法鞏固與提高

一、數論    1.數   整數、自然數(大於等於0的整數)、正整數(大於0的整數)、負整數、非負整數、非正整數、非零整數、奇數偶數。   2.整除性   設a,b∈Z,如果存在c∈Z並且a=bc,則

NOIP複賽複習(八)STL演算法與樹結構模板

STL演算法 STL 演算法是一些模板函式,提供了相當多的有用演算法和操作,從簡單如for_each(遍歷)到複雜如stable_sort(穩定排序),標頭檔案是:#include <algorithm>。常用STL 演算法庫包括:sort快速排序演算法、二分

NOIP複賽複習(七)STL容器與字串模板

STL容器 STL 容器是一些模板類,提供了多種組織資料的常用方法。常用的STL容器包括pair(組合)、list(列表,類似於連結串列)、vector(向量,類似於陣列)、priority_queue(優先佇列)、set(集合)、map(對映)、stack(棧)等,通過模板的引數