【板子】數據結構 && 圖論 && 數論

更新

2020-06-25 重新排版

2017-11-09 第一次整理上傳

前言

自用板子,經測試代碼均正確,可以放心食用,源自於17年準備NOIP(當時還不會md😭)。大學程序設計課對板子進行完善。

數據結構

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<functional>
#define LL long long
using namespace std;
inline int get_num()
{
	char c;
	int f=1,num=0;
	while((c=getchar())==' '||c=='\n'||c=='\r');
	if(c=='-') f=-1;
	else num=c-'0';
	while(isdigit(c=getchar())) num=num*10+c-'0';
	return num*f;
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

線段樹

inline void push_up(int p){
	tr[p].w=tr[p<<1].w+tr[p<<1|1].w;
}
inline void push_down(int p){
	if(!tr[p].lazy) return ;
	tr[p<<1].w+=tr[p].lazy*(tr[p<<1].r-tr[p<<1].l+1);
	tr[p<<1].lazy+=tr[p].lazy;
	tr[p<<1|1].w+=tr[p].lazy*(tr[p<<1|1].r-tr[p<<1|1].l+1);
	tr[p<<1|1].lazy+=tr[p].lazy;
	tr[p].lazy=0;
}
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	if(l==r){
		tr[p].w=get_num();
		return ;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
	push_up(p);
}
void add(int p,int l,int r,LL k){
	if(tr[p].l==l&&tr[p].r==r){
		tr[p].w+=(r-l+1)*k;
		tr[p].lazy+=k;
		return ;
	}
	push_down(p);
	int mid=(tr[p].r+tr[p].l)>>1;
	if(r<=mid) add(p<<1,l,r,k);
	else if(l>mid) add(p<<1|1,l,r,k);
	else{
		add(p<<1,l,mid,k);add(p<<1|1,mid+1,r,k);
	}
	push_up(p);
	
}
LL query(int p,int l,int r){
	if(tr[p].l==l&&tr[p].r==r){
		return tr[p].w;
	}
	LL ans=0;
	push_down(p);
	int mid=(tr[p].r+tr[p].l)>>1;
	if(r<=mid) ans=query(p<<1,l,r);
	else if(l>mid) ans=query(p<<1|1,l,r);
	else{
		ans=query(p<<1,l,mid)+query(p<<1|1,mid+1,r);
	}
	push_up(p);
	return ans;
	
}
int main()
{
	int n,m;n=get_num();m=get_num();
	build(1,1,n);
	int c,x,y;LL k;
	for(int i=1;i<=m;i++){
		c=get_num();x=get_num();y=get_num();
		if(c==1){
			k=get_num();
			add(1,x,y,k);
		}else{
			cout<<query(1,x,y)<<'\n';
		}
	}
	return 0;
}

樹鏈剖分

inline void push_up(int p){
	tr[p].w=tr[p<<1].w+tr[p<<1|1].w;
}
inline void push_down(int p){
	if(!tr[p].lazy) return ;
	tr[p<<1].w+=tr[p].lazy*(tr[p<<1].r-tr[p<<1].l+1);
	tr[p<<1].lazy+=tr[p].lazy;
	tr[p<<1|1].w+=tr[p].lazy*(tr[p<<1|1].r-tr[p<<1|1].l+1);
	tr[p<<1|1].lazy+=tr[p].lazy;
	tr[p].lazy=0;
}
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	if(l==r){
		tr[p].w=w[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	push_up(p);
}
void add(int p,int l,int r,LL k){
	if(tr[p].l==l&&tr[p].r==r)
	{
		tr[p].w+=(r-l+1)*k;
		tr[p].lazy+=k;
		return ;
	}
	push_down(p);
	int mid=(tr[p].l+tr[p].r)>>1;
	if(r<=mid) add(p<<1,l,r,k);
	else if(l>mid) add(p<<1|1,l,r,k);
	else{
		add(p<<1,l,mid,k);add(p<<1|1,mid+1,r,k);
	}
	push_up(p);
}
LL query(int p,int l,int r){
	if(tr[p].l==l&&tr[p].r==r)
	{
		return tr[p].w;
	}
	LL ans=0;
	push_down(p);
	int mid=(tr[p].l+tr[p].r)>>1;
	if(r<=mid) ans=query(p<<1,l,r);
	else if(l>mid) ans=query(p<<1|1,l,r);
	else{
		ans=query(p<<1,l,mid)+query(p<<1|1,mid+1,r);
	}
	push_up(p);
	return ans;
}
void dfs_1(int x){
	siz[x]=1;
	for(int i=0;i<v[x].size();i++){
		if(cur!=f[x]){
			f[cur]=x;
			deep[cur]=deep[x]+1;
			dfs_1(cur);
			siz[x]+=siz[cur];
			if(siz[son[x]]<siz[cur]) son[x]=cur;
		}
	}
}
void dfs_2(int x,int p){
	id[x]=++tot;w[tot]=d[x];top[x]=p;
	if(son[x]) dfs_2(son[x],p);
	for(int i=0;i<v[x].size();i++){
		if(cur!=f[x]&&cur!=son[x]){
			dfs_2(cur,cur);
		}
	}
}
void modify(int a,int b,int k){
	while(top[a]!=top[b]){
		if(deep[top[a]]>deep[top[b]]) swap(a,b);
		add(1,id[top[b]],id[b],k);
		b=f[top[b]];
	}if(deep[a]>deep[b]) swap(a,b);
	add(1,id[a],id[b],k);
}
LL find(int a,int b){
	LL ans=0;
	while(top[a]!=top[b]){
		if(deep[top[a]]>deep[top[b]]) swap(a,b);
		ans+=query(1,id[top[b]],id[b]); ans%=MOD;
		b=f[top[b]];
	}if(deep[a]>deep[b]) swap(a,b);
	ans+=query(1,id[a],id[b]);
	return ans%MOD;
}
int main()
{
	int n,m,root;
	n=get_num();m=get_num();root=get_num();MOD=get_num();
	for(int i=1;i<=n;i++) d[i]=get_num();
	for(int i=1;i<n;i++){
		int a,b;
		a=get_num();b=get_num();v[a].push_back(b);
		v[b].push_back(a);
	}
	dfs_1(root);
	dfs_2(root,root);
	build(1,1,n);
	int c,x,y;LL z;
	for(int i=1;i<=m;i++){
		c=get_num();x=get_num();
		if(c==1){
			y=get_num();
			z=get_num();
			modify(x,y,z%MOD);
		}else if(c==2)
		{
			y=get_num();
			cout<<find(x,y)<<'\n';
		}else if(c==3){
			z=get_num();
			add(1,id[x],id[x]+siz[x]-1,z%MOD);
		}else if(c==4){
			cout<<query(1,id[x],id[x]+siz[x]-1)%MOD<<'\n';
		}
	}
	return 0;
}

最小生成樹

bool cmp(const re &a,const re &b){
	return a.z<b.z;
}
int find(int x){
	if(f[x]==x) return x;
	return f[x]=find(f[x]);
}
int main()
{
	int n,m;n=get_num();m=get_num();
	for(int i=1;i<=m;i++){
		v[i].x=get_num();v[i].y=get_num();v[i].z=get_num();
	}
	sort(v+1,v+1+m,cmp);
	LL ans=0,cnt=0;
	for(int i=1;i<=n;i++) f[i]=i;
	for(int i=1;i<=m;i++){
		if(find(v[i].x)!=find(v[i].y))
		{
			++cnt; ans+=v[i].z;
			f[find(v[i].x)]=find(v[i].y);
			if(cnt==n-1){
				break;
			}
		}
	}
	if(cnt==n-1)cout<<ans;
	else cout<<"orz";
	return 0;
}

並查集

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

初始化 for(int i=1;i<=n;i++) f[i]=i;

樹狀數組 1

在全局有個nn,主函數有個nn,讀入nn的時候,全局相當於nn是0。

樹狀數組 2

void modify(int x,LL p){
	for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=p;
	//for和tr的i不要寫錯啊
}
LL query(int x){
	LL ans=0;
	for(int i=x;i;i-=lowbit(i)) ans+=tr[i];
	return ans;
}
  • modify(x,k);modify(y+1,-k); 寫的 modify(x,k);modify(y+1,k);

  • for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=p; 寫的 for(int i=x;i<=n;i+=lowbit(i)) tr[x]+=p;

priority_queue<int,vector<int>,greater<int> >Q;
	int n;n=get_num();
	int c,x;
	for(int i=1;i<=n;i++){
		c=get_num();
		if(c==1){
			x=get_num();
			Q.push(x);
		}else if(c==2){
			cout<<Q.top()<<'\n';
		}else {
			Q.pop();
		}
	}

圖論

最近公共祖先(LCA)

void dfs(int x){
	vis[x]=1;
	for(int b=fa[x];b;b=v[b].nxt){
		if(!vis[cur])
		{
			deep[cur]=deep[x]+1;
			lca[cur][0]=x;
			dfs(cur);
		}
	}
}
int query(int a,int b)
{
	if(deep[a]>deep[b]) swap(a,b);
	for(int i=19;i>=0;i--) if(deep[lca[b][i]]>=deep[a]) b=lca[b][i];
	if(a==b) return a;
	for(int i=19;i>=0;i--){// 是大於等於0不是(int i=19;i;i--)
		if(lca[a][i]!=lca[b][i]){
			a=lca[a][i];b=lca[b][i];
		}
	}
	return lca[a][0];
}
	deep[s]=1;
	dfs(s);
	for(int j=1;j<=19;j++){
		for(int i=1;i<=n;i++){
			lca[i][j]=lca[lca[i][j-1]][j-1];
		}
	}

vector TLE 了倆點 還是好好用struct

最近公共祖先(tarjan)

void tarjan(int x){
	vis[x]=1;
	f[x]=x;
	for(int b=fa[x];b;b=v[b].nxt){
		if(!vis[cur]){
			tarjan(cur);
			f[find(cur)]=x;
		}
	}
	for(int b=faa[x];b;b=qv[b].nxt){
		if(vis[qv[b].to]){
			qv[b^1].ans=qv[b].ans=find(qv[b].to);
		}
	}
}
void add(int x,int y){
	v[++p].to=y;
	v[p].nxt=fa[x];
	fa[x]=p;
}

v[++p].to=y;y寫成了x

最近公共祖先(樹剖)

void dfs_1(int x){
	siz[x]=1;
	for(int b=fa[x];b;b=v[b].nxt){
		if(cur!=f[x]){
			f[cur]=x;
			deep[cur]=deep[x]+1;
			dfs_1(cur);
			siz[x]+=siz[cur];//忘寫了一開始
			if(siz[son[x]]<siz[cur]) son[x]=cur;
		}
	}
}
void dfs_2(int x,int p){
	top[x]=p;
	if(son[x]) dfs_2(son[x],p);
	for(int b=fa[x];b;b=v[b].nxt){
		if(cur!=f[x]&&cur!=son[x]){
			dfs_2(cur,cur);
		}
	}
}
int query(int a,int b){
	while(top[a]!=top[b]){
		if(deep[top[a]]>deep[top[b]]) swap(a,b);
		b=f[top[b]];
	}
	return (deep[a]<=deep[b])? a : b;
}

dfs_1的時候
dfs_1(cur)
忘記寫:siz[x]+=siz[cur];
就相當於沒有長長的鏈鏈了
就跳的很慢很慢了 然後就T了
其實常數是比LCA小的 OK的說

三分法

int n;
double v[20];
double eps=1e-7;
double find(double x){ //find類型不要寫錯
	double ans=v[n+1];
	double p=1;
	for(int i=n;i;i--){
		p*=x;
		ans+=v[i]*p;
	}
	return ans;
}
int main()
{
	double l,r,mid,midd;
	cin>>n>>l>>r;
	for(int i=1;i<=n+1;i++) cin>>v[i];
	while(l+eps<=r){
		mid=(l+r)/2;
		midd=(l+mid)/2;
		if(find(midd)<find(mid)) l=midd;
		else r=mid;
	}
	printf("%.5lf",l);
	return 0;
}

double 類型用的get_num()讀進去了
其實應該用cin>>
能過樣例也是奇蹟

最長公共子序列

	int n;n=get_num();
	for(int i=1;i<=n;i++) f[get_num()]=i;
	for(int i=1;i<=n;i++){
		int c=f[get_num()];
		if(c>dp[len]) dp[++len]=c;
		else{
			int l=1,r=len,mid;
			while(l<=r){
				mid=(l+r)>>1;
			    if(dp[mid]>c) r=mid-1;
			    else l=mid+1;
			}dp[l]=c;
		}		
	}
	cout<<len;

單源最短路徑

	int n,m,s;n=get_num();m=get_num();s=get_num();
	for(int i=1;i<=m;i++){
		int a,b,c;
		a=get_num();b=get_num();c=get_num();
		add(a,b,c);//注意單項邊還是雙向邊
	}
	for(int i=1;i<=n;i++) d[i]=2147483647;
	d[s]=0;
	vis[s]=1;//忘寫了一開始
	Q.push(s);
	while(!Q.empty()){
		int h=Q.front();
		vis[h]=0;
		Q.pop();
		for(int b=fa[h];b;b=v[b].nxt)
		{
			if(d[cur]>d[h]+v[b].w)
			{
				d[cur]=d[h]+v[b].w;
				if(!vis[cur])
				{
					vis[cur]=1;
					Q.push(cur);
				}
			}
		}
	}

queuevis[h]進來的時候 沒有寫vis[h]=0;

負環

void dfs(int x){
	if(ans) return ;
	vis[x]=1;
	for(int b=fa[x];b;b=v[b].nxt){
		if(d[cur]>d[x]+v[b].w){
			d[cur]=d[x]+v[b].w;
			if(vis[cur])
			{
				ans=1;
				break;
			}
			dfs(cur);
		}
	}
	vis[x]=0;
}
	while(t)
	{
		t--;int n,m;
		memset(vis,0,sizeof(vis));
		memset(d,0,sizeof(d));
		memset(fa,0,sizeof(fa));p=0;
		n=get_num();m=get_num();
		for(int i=1;i<=m;i++){
			int a,b,w;
			a=get_num();b=get_num();w=get_num();
			add(a,b,w);
			if(w>=0) add(b,a,w); 
		}
		ans=0;
		for(int i=1;i<=n;i++){
			dfs(i);
			if(ans) break;
		}
		if(ans) cout<<"YE5\n";
		else cout<<"N0\n";
	}

二分圖匹配 再打一遍

int dfs(int x){
	for(int i=0;i<v[x].size();i++){
		if(!vis[cur])
		{
			vis[cur]=1;
			if(!match[cur]||dfs(match[cur]))
			{
				match[cur]=x;
				match[x]=cur;
				return 1;
			}
		}
	}
	return 0;
}
int n;
int query(){
	int ans=0;
	for(int i=1;i<=n;i++){
		if(!match[i]){
			memset(vis,0,sizeof(vis));
			if(dfs(i)) ans++;
		}
	}
	return ans;
}
int main()
{
	int m,e;n=get_num();m=get_num();e=get_num();
	for(int i=1;i<=e;i++){
		int a,b;a=get_num();b=get_num();
		if(b<=m) v[a].push_back(b+n);
	}
	cout<<query();
	return 0;
}

縮點 再打一遍

void tarjan(int x){
	my_s.push(x);in_s[x]=1;//注意不要忘了
	dfn[x]=low[x]=++tot;
	for(int b=fa[x];b;b=v[b].nxt){
		if(!dfn[cur]){
			tarjan(cur);
			low[x]=min(low[x],low[cur]);
		} else if(in_s[cur]) low[x]=min(low[x],dfn[cur]);
	}
	if(low[x]==dfn[x])
	{
		++bcnt;
		while(my_s.top()!=x){
			fd[my_s.top()]=bcnt;d[bcnt]+=w[my_s.top()];in_s[my_s.top()]=0;my_s.pop();
		}
		d[bcnt]+=w[my_s.top()];fd[my_s.top()]=bcnt;in_s[my_s.top()]=0;my_s.pop();
	}
}

void build(){
	for(int i=1;i<=n;i++){
		for(int b=fa[i];b;b=v[b].nxt)
		{
			if(fd[i]!=fd[cur])
			{
				qv[fd[i]].push_back(fd[cur]);
			}
		}
	}
}
int dfs(int x){
	if(dp[x]) return dp[x];
	for(int i=0;i<qv[x].size();i++){
		dp[x]=max(dp[x],dfs(qv[x][i]));
	}
	dp[x]+=d[x];
	return dp[x];
}

割頂(割點)

void tarjan(int x){
	dfn[x]=low[x]=++tot;
	int rt=0;
	for(int b=fa[x];b;b=v[b].nxt){
		if(!dfn[cur]){
			rt++;
			f[cur]=f[x];
			tarjan(c			if(low[cur]>=dfn[x]&&f[x]!=x&&!vis[x]) vis[x]=1,ans++;//重要
		}else  low[x]=min(low[x],dfn[cur]);
	}
	if(f[x]==x&&rt>=2) ans++,vis[x]=1;
}

樹上差分

LL fast_pow(LL a,LL p,LL k){
	LL ans=(a==0)?0:1;
	a%=k;
	for(;p;p>>=1,a=(a*a)%k)
	{
		if(p&1) ans=(ans*a)%k;
	}return ans;
}
int main()
{
	LL n,l,r;cin>>n>>l>>r;
	for(int i=1;i<=n;i++){
		v[i].m=get_num();v[i].a=get_num();
	}
	LL M=1;
	for(int i=1;i<=n;i++) M*=v[i].m;
	for(int i=1;i<=n;i++){
		v[i].M=M/v[i].m;
		v[i].k=fast_pow(v[i].M,v[i].m-2,v[i].m);
	}
	LL ans=0;
	for(int i=1;i<=n;i++) ans=(ans+v[i].a*v[i].M*v[i].k)%M;
	//cout<<ans;
	LL anss=0;
	if(r>=ans) anss=(r-ans)/M+1;
	if(l-1>=ans) anss-=(l-ans-1)/M+1;
	if(anss==0) cout<<0<<'\n'<<0;
	else{
		cout<<anss<<'\n';
		if(l-1>=ans){
			cout<<((l-1-ans)/M+1)*M+ans;
		}else cout<<ans;
	}
	return 0;
}

最大流量

const int maxn=50010;
struct re{
	int fd,to,nxt,ans;
}qv[maxn<<2];
vector<int> v[maxn];
int p=1,fa[maxn],vis[maxn],d[maxn],f[maxn],fath[maxn];int n,k;
inline void add(int x,int y){
	qv[++p].to=y;
	qv[p].nxt=fa[x];
	qv[p].fd=x;
	fa[x]=p;
}
inline int get_num()
{
	char c;
	int f=1,num=0;
	while((c=getchar())==' '||c=='\n'||c=='\r');
	if(c=='-') f=-1;
	else num=c-'0';
	while(isdigit(c=getchar())) num=num*10+c-'0';
	return num*f;
}
int find(int x){
	if(f[x]==x) return x;
	return f[x]=find(f[x]);
}
void tarjan(int x){
	vis[x]=1;
	f[x]=x;
	for(int i=0;i<v[x].size();i++){
		if(!vis[cur]){
			fath[cur]=x;
			tarjan(cur);
			f[find(cur)]=x;
		}
	}
	for(int b=fa[x];b;b=qv[b].nxt){
		if(vis[qv[b].to]){
			qv[b].ans=qv[b^1].ans=find(qv[b].to);
		}
	}
}
void dfs(int x){
	vis[x]=1;
	for(int i=0;i<v[x].size();i++){
		if(!vis[cur]){
			dfs(cur);
			d[x]+=d[cur]; 
		}
	}
}
int query(){
	for(int i=2;i<=p;i+=2){
		++d[qv[i].fd];++d[qv[i].to];--d[qv[i].ans];
		--d[fath[qv[i].ans]];
	}
	memset(vis,0,sizeof(vis));
	dfs(1);
	int ans=0;
	for(int i=1;i<=n;i++){
		ans=max(ans,d[i]);
	}return ans;
}
int main()
{
	n=get_num();k=get_num();
	for(int i=1;i<n;i++){
		int a,b;a=get_num();b=get_num();
		v[a].push_back(b);v[b].push_back(a);
	}
	for(int i=1;i<=k;i++){
		int a,b;a=get_num();b=get_num();
		add(a,b);add(b,a);
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]) tarjan(i);
	}
	cout<<query();
	return 0;
}

Floyd

	int n;n=get_num();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			v[i][j]=get_num();
		}
	}for(int i=0;i<=n;i++) v[i][i]=0;
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				v[i][j]=min(v[i][j],v[i][k]+v[k][j]);
			}
		}
	}
	int m=get_num();
	for(int i=1;i<=m;i++){
		int a,b;a=get_num();b=get_num();
		cout<<v[a][b]<<'\n';
	}

堆優化dijkstra

struct re{
	int d,k;
};
struct cmp{
	inline bool operator () (re a, re b){
		return a.d>b.d;
	}
}; 
priority_queue<re,vector<re>,cmp >Q;
int main()
{
	int n,m;
	re s;
	n=get_num();m=get_num();s.k=get_num();
	for(int i=1;i<=m;i++){
		int a,b,c;a=get_num();b=get_num();c=get_num();
		add(a,b,c);
	}
	for(int i=1;i<=n;i++) d[i]=2147483647;
	d[s.k]=0;re B;s.d=0;
	Q.push(s);
	while(!Q.empty()){
		re h=Q.top();
		Q.pop();
		if(vis[h.k]) continue;
		vis[h.k]=1;
		for(int b=fa[h.k];b;b=v[b].nxt){
			if(d[cur]>d[h.k]+v[b].w){
				d[cur]=d[h.k]+v[b].w;
				B.d=d[cur];B.k=v[b].to;
				Q.push(B);
			}
		}
	}
	for(int i=1;i<=n;i++) cout<<d[i]<<" ";
	return 0;
}

數論

快速冪

LL fast_pow(LL a,LL p,LL k){
	LL ans=(a==0)?0:1;//注意是a不是p
	a%=k;
	for(;p;p>>=1,a=(a*a)%k)
	{
		if(p&1) ans=(ans*a)%k;
	}
	return ans;
}

gcd

int gcd(int a,int b)
{
	if(b==0) return a;
	return gcd(b,a%b);
}

exgcd 同餘方程

void exgcd(LL a,LL b,LL &x,LL &y){
	if(b==0){
		x=1,y=0;return ;
	}
	exgcd(b,a%b,x,y);
	LL x2=x,y2=y;
	x=y2;y=x2-(a/b)*y2;//手推即可
}

線性篩素數

	int n,m;n=get_num();m=get_num();
	for(int i=2;i<=n;i++){
		if(!vis[i]) pri[++cnt]=i;
		for(int j=1;j<=cnt&&pri[j]*i<=n;j++){
			vis[i*pri[j]]=1;//注意誰%誰 後者%不動
			if(i%pri[j]==0) break;
		}
	}
	vis[1]=1;//注意1首先啥都不是 其次他不是素數
	for(int i=1;i<=m;i++){
		if(vis[get_num()]) cout<<"No\n";
		else cout<<"Yes\n";
	}

沒有考慮vis[1]=1的情況 詳情看日記

矩陣快速冪

struct matrix{
	LL n,m;
	LL v[110][110];
	matrix(){
		memset(v,0,sizeof(v));
	}
	void prinf(){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<v[i][j]<<" ";
			}cout<<'\n';
		}
	}
};
matrix operator * (matrix a,matrix b){
	matrix res;res.n=b.n;res.m=a.m;
	for(int i=1;i<=res.n;i++){
		for(int j=1;j<=res.m;j++){
			for(int k=1;k<=a.n;k++){
				res.v[i][j]=(res.v[i][j]+a.v[k][j]*b.v[i][k])%MOD;
			}
		}
	}
	return res;
} 
inline LL get_num()
{
	char c;
	LL f=1,num=0;
	while((c=getchar())==' '||c=='\n'||c=='\r');
	if(c=='-') f=-1;
	else num=c-'0';
	while(isdigit(c=getchar())) num=num*10+c-'0';
	return num*f;
}
matrix fast_pow(matrix a,LL p){
	matrix ans;
	ans.n=a.n;ans.m=a.m;
	for(int i=1;i<=ans.n;i++) ans.v[i][i]=1;
	for(;p;p>>=1,a=(a*a))
	{
		if(p&1) ans=(ans*a);
	}return ans;
}
int main()
{
	LL n,k;
	matrix a;
	a.n=a.m=n=get_num();k=get_num();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			a.v[i][j]=(get_num())%MOD;
		}
	}
	fast_pow(a,k).prinf();
	return 0;
}

fast_pow裏面p>>=1 寫的p>>1 get_num()沒改LL

乘法逆元

	LL n,p;cin>>n>>p;
	inv[1]=1%p;cout<<inv[1]<<'\n';
	for(int i=2;i<=n;i++){
		inv[i]=(p-p/i)*inv[p%i]%p;//由p%i+(p/i)*i=p開始
		cout<<inv[i]<<'\n';
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章