1. 程式人生 > >noip複習:聯賽常用模板

noip複習:聯賽常用模板

快速排序

#include<bits/stdc++.h>
using namespace std;

#define maxn 100000
#define read(x) scanf("%d",&x)

int n;
int a[maxn+5];

int main() {
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++) printf("%d ",a[i]);
	return 0;
}

並查集:
注意:不能忘了路徑壓縮

#include<bits/stdc++.h>
using namespace std; #define maxn 10000 #define read(x) scanf("%d",&x) int n,m; int fa[maxn+5]; int find(int x) { if(!fa[x]) return x; return fa[x]=find(fa[x]); } int main() { read(n),read(m); while(m--) { int x,y,z; read(z),read(x),read(y); int fa1=find(x),fa2=find(y); if(z==1) { if
(fa1==fa2) continue; else fa[fa1]=fa2; } else { if(fa1==fa2) printf("Y\n"); else printf("N\n"); } } return 0; }

快速冪
注意:在最後輸出ans時要再模一次p,以免被指數為0模數為1的情況卡掉

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define read(x) scanf("%d",&x)

int a,b,p;

int main()
{ read(a),read(b),read(p); int aa=a,bb=b; int ans=1; while(b) { if(b&1) ans=(ll)ans*a%p; b>>=1,a=(ll)a*a%p; } printf("%d^%d mod %d=%d",aa,bb,p,ans%p); return 0; }

線性篩判素數
注意:
1、一定要背熟模板
2、不要忘寫 &&i*prm[j]<=n 導致陣列越界

#include<bits/stdc++.h>
using namespace std;

#define maxn 10000000
#define read(x) scanf("%d",&x)

int n,m;
int Phi[maxn+5];
vector<int> prm;

void makephi() {
	Phi[1]=1;
	for(int i=2;i<=n;i++) {
		Phi[i]=i;
	}
	for(int i=2;i<=n;i++) {
		if(Phi[i]==i) Phi[i]--,prm.push_back(i);
		for(int j=0;j<prm.size()&&i*prm[j]<=n;j++) {
			int x=prm[j];
			if(i%x) Phi[i*x]=Phi[i]*x;
			else Phi[i*x]=Phi[i]*Phi[x];
		}
	}
}

int main() {
	read(n),read(m);
	makephi();
	while(m--) {
		int x;
		read(x);
		if(Phi[x]==x-1) printf("Yes\n");
		else printf("No\n");
	}
	
	return 0;
}

堆(優先佇列)
注意:priority_queue是大根堆,若要使用小跟堆需要push相反數,或使用struct封裝後定義小於運算子。

#include<bits/stdc++.h>
using namespace std;

#define read(x) scanf("%d",&x)

priority_queue<int> que;

int main() {
	int n;
	read(n);
	while(n--) {
		int opr;
		read(opr);
		if(opr==1) {
			int x;
			read(x);
			que.push(-x);
		} else if(opr==2) printf("%d\n",-que.top());
		else que.pop();
	}
	
	return 0;
}

字串雜湊
注意:
1、可以用 unsigned long long (ull)的自然溢位處理取模問題
2、使用雙雜湊不容易產生衝突

#include<bits/stdc++.h>
using namespace std;

#define maxn 10000
#define maxm 1500
#define ull unsigned long long
#define read(x) scanf("%d",&x)

struct Pair{
	ull x,y;
	Pair(){}
	Pair(ull xx,ull yy) {x=xx,y=yy;}
	bool operator < (const Pair& oth) const {
		return x<oth.x||(x==oth.x&&y<oth.y);
	} 
	bool operator == (const Pair& oth) const {
		return x==oth.x&&y==oth.y;
	}
};

int n;
Pair hsh[maxn+5];

const int md1=13,md2=131;

void make_hash(int x,char* s,int m) {
	ull hsh1=0,hsh2=0;
	for(int i=0;i<m;i++) {
		hsh1=hsh1*md1+s[i]+1;
		hsh2=hsh2*md2+s[i]+1;
	}
	hsh[x]=Pair(hsh1,hsh2);
}

int main() {
	read(n);
	for(int i=1;i<=n;i++) {
		char s[maxm+5];
		scanf("%s",s);
		make_hash(i,s,strlen(s));
	}
	
	sort(hsh+1,hsh+n+1);
	
	int ans=0;
	for(int i=1;i<=n;i++) {
		if(hsh[i]==hsh[i-1]) continue;
		ans++;
	}
	
	printf("%d",ans);
		
	return 0;
}

最小生成樹
注意:
1、正向定義小於運算子
2、圖不連通的判斷方法是求出的最小生成樹的邊數不等於n-1
3、邊集的陣列大小要開maxm,開成了maxn就徹底涼了
4、接上,n==m時一定要注意,不要把n、m弄反

#include<bits/stdc++.h>
using namespace std;

#define maxn 5000
#define maxm 200000
#define read(x) scanf("%d",&x)

struct Edge{
	int x,y,z;
	Edge(){}
	Edge(int xx,int yy,int zz) {
		x=xx,y=yy,z=zz;
	}
	bool operator < (const Edge& oth) const {
		return z<oth.z;
	}
};

int n,m;
Edge e[maxm+5];
int fa[maxn+5];

int find(int x) {
	if(fa[x]) return fa[x]=find(fa[x]);
	else return x;
}

int kruskal() {
	int cnt=0,s=0;
	for(int i=1;i<=m;i++) {
		int fa1=find(e[i].x),fa2=find(e[i].y);
		if(fa1==fa2) continue;
		fa[fa1]=fa2;
		cnt++;
		s+=e[i].z;
	}
	if(cnt==n-1) return s;
	else return -1;
}

int main() {
	read(n),read(m);
	for(int i=1;i<=m;i++) read(e[i].x),read(e[i].y),read(e[i].z);
	sort(e+1,e+m+1);
	int ans=kruskal();
	if(ans==-1) printf("orz");
	else printf("%d",ans);	
	return 0;
}
#include<bits/stdc++.h>
using namespace std;

#define maxn 100000
#define maxm 200000
#define inf ((int)1e9)
#define read(x) scanf("%d",&x)

struct Edge{
	int x,y,z;
	Edge(){}
	Edge(int xx,int yy,int zz) {z=zz,y=yy,z=zz;}
};

struct Node{
	int y,z;
	Node(){}
	Node(int yy,int zz){y=yy,z=zz;}
	bool operator < (const Node& oth) const {
		return z>oth.z;
	}
};

int n,m,s;
vector<Edge> g[maxn+5];

int dist[maxn+5];
priority_queue<Node> que;
bool vis[maxn+5];

void readin() {
	read(n),read(m),read(s);
	for(int i=1;i<=m;i++) {
		int x,y,z;
		read(x),read(y),read(z);
		g[x].push_back(Edge(x,y,z));
	}
}

void dijkstra() {
	for(int i=1;i<=n;i++) if(i!=s) dist[i]=inf;
	que.push(Node(s,0));
	while(!que.empty()) {
		int h=que.top().y;
		que.pop();
		if(vis[h]) continue;
		vis[h]=true;
		for(int i=0;i<g[h].size();i++) {
			int y=g[h][i].y;
			if(dist[y]>dist[h]+g[h][i].z) {
				dist[y]=dist[h]+g[h][i].z;
				que.push(Node(y,dist[y]));
			}
		}
	}
	for(int i=1;i<=n;i++) printf("%d ",dist[i]);
}

int main() {
	readin();
	dijkstra();	
	return 0;
}
#include<bits/stdc++.h>
using namespace std;

#define maxn 100
#define maxm 10000
#define read(x) scanf("%d",&x)
#define inf (1<<30)

int n,m;
int a[maxm+5];
int g[maxn+5][maxn+5];
int dist[maxn+5][maxn+5];

void readin() {
	read(n),read(m);
	for(int i=1;i<=m;i++) read(a[i]);
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) read(g[i][j]);
}

void floyd() {
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dist[i][j]=g[i][j];
	for(int k=1;k<=n;k++) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {