2019.9.17考试

数学老师的报复

  • f [ 1 ] = f [ 2 ] = 1 f[1]=f[2]=1 f[1]=f[2]=1 f [ n ] = ( A f [ n − 1 ] + B f [ n − 2 ] ) f[n]=(Af[n-1]+Bf[n-2]) f[n]=(Af[n1]+Bf[n2])% 7 7 7, n < = 2147483648 n<=2147483648 n<=2147483648
  • 矩阵乘法模板题,转置矩阵为
    在这里插入图片描述
#include <bits/stdc++.h>
using namespace std;
#define mod 7
long long A,B,n;

struct Matrix {
   long long a[5][5];
   Matrix() {memset(a,0,sizeof(a));}
   Matrix operator * (const Matrix &b) const {
   	Matrix res;
   	for(int i=1;i<=2;++i) {
   		for(int j=1;j<=2;++j) {
   			for(int k=1;k<=2;++k) {
   				res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j])%mod;
   			}
   		}
   	}
   	return res;
   }
} ans,base;

void readda_() {
   scanf("%lld%lld%lld",&A,&B,&n);
   if(n<=2) {printf("1");return;}
   n-=2;
   ans.a[1][1]=ans.a[1][2]=1;
   base.a[1][1]=A;base.a[1][2]=1;
   base.a[2][1]=B;base.a[2][2]=0;
   while(n) {
   	if(n&1) ans=ans*base;
   	base=base*base;
   	n>>=1;
   }
   printf("%lld",ans.a[1][1]);
}
  • 当然,由于答案是 m o d 7 mod7 mod7,所以 f f f数组是循环函数,可以用判断循环节的方式 A C AC AC
#include <bits/stdc++.h>
using namespace std;
#define maxn 25000000

long long A,B,n;
int f[maxn];

void readda_() {
	scanf("%lld%lld%lld",&A,&B,&n);
	A%=7;B%=7;bool flag=false;
	f[1]=f[2]=1;int cnt;
	for(int i=3;i<=n;++i) {
		f[i]=(A*f[i-1]+B*f[i-2])%7;
		if(f[i]==1&&f[i-1]==1) {flag=true;cnt=i-2;break;}
	}
	if(!flag) {printf("%d",f[n]%7);return;}
	n%=cnt;if(!n) n=cnt;
	printf("%d",f[n]%7);
}

int main() {
	readda_();
	return 0;
}

物理和生物老师的战争

化学竞赛的的大奖

在这里插入图片描述
在这里插入图片描述

  • 先缩点,在求每个点到能去其他点的最远距离?
  • 可以 n n n D i j k s t r a Dijkstra Dijkstra 40 40 40
  • 可以发现:缩点完后图为一棵树,而树上一个点到其他点的最远距离肯定在直径上
  • d f s dfs dfs两次求出两个直径端点,再 d f s dfs dfs维护出每个点到两个端点的距离,则答案为 m a x ( d 1 [ t 1 ] , d 2 [ t 2 ] ) max(d_1[t_1],d_2[t_2]) max(d1[t1],d2[t2])
  • 对于变量重复的情况可以用 n a m e s p a c e namespace namespace
#include <bits/stdc++.h>
using namespace std;
#define maxn 20010
#define maxm 200010

int n,m,co[maxn],col=0;
struct node {
	int x,y,z;
}AK[maxm];

inline int read_() {
	int x_=0,f_=1;char c_=getchar();
	while(c_<'0'||c_>'9') {if(c_=='-') f_=-1;c_=getchar();}
	while(c_>='0'&&c_<='9') {x_=(x_<<1)+(x_<<3)+c_-'0';c_=getchar();}
	return x_*f_;
}

namespace TT {
	int sze=1,head[maxn],dfn[maxn],low[maxn],st[maxn],cnt=0,top=0;
	struct edge {
		int v,nxt;
	}e[maxm<<1];
	inline void add_(int u,int v) {
		e[++sze].v=v;
		e[sze].nxt=head[u];
		head[u]=sze;
	}
	void Tarjan_(int u,int from) {
		dfn[u]=low[u]=++cnt;
		st[++top]=u;
		for(int i=head[u];~i;i=e[i].nxt) {
			if(i==(from^1)) continue;
			int v=e[i].v;
			if(!dfn[v]) {
				Tarjan_(v,i);
				low[u]=min(low[u],low[v]);
			}
			else if(!co[v]) low[u]=min(low[u],dfn[v]);
		}
		if(dfn[u]==low[u]) {
			co[u]=++col;
			while(st[top]!=u) {
				co[st[top]]=col;
				--top;
			}
			--top;
		} 
	}
	inline void work_() {
		memset(head,-1,sizeof(head));
		for(int i=1;i<=m;++i) {
			add_(AK[i].x,AK[i].y);
			add_(AK[i].y,AK[i].x);
		} 
		for(int i=1;i<=n;++i) if(!dfn[i]) Tarjan_(i,0);
	}
}

namespace ac {
	int bel[maxn],maxd=0,root,sze=0,head[maxn],d[maxn],dis[maxn];
	struct edge {
		int v,w,nxt;
	}e[maxm<<1]; 
	inline bool cmp_(node aa,node bb) {return aa.z < bb.z;} 
	int find_(int x) {if(bel[x]==x) return x;return bel[x]=find_(bel[x]);}
	inline void add_(int u,int v,int w) {
		e[++sze].v=v;
		e[sze].w=w;
		e[sze].nxt=head[u];
		head[u]=sze;
	}
	inline void rebuild_() {
		for(int i=1;i<=m;++i) {
			AK[i].x=co[AK[i].x];
			AK[i].y=co[AK[i].y];
		} 
		for(int i=1;i<=col;++i) bel[i]=i;
		sort(AK+1,AK+1+m,cmp_);
		memset(head,-1,sizeof(head));
		for(int i=1;i<=m;++i) {
			if(AK[i].x==AK[i].y) continue;
			int fx=find_(AK[i].x),fy=find_(AK[i].y);
			if(fx!=fy) {
				bel[fx]=fy;
				add_(AK[i].x,AK[i].y,AK[i].z);
				add_(AK[i].y,AK[i].x,AK[i].z);
			}
		}
	}
	void dfs_1_(int u,int fa) {
		for(int i=head[u];~i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if(v==fa) continue;
			d[v]=d[u]+w;
			if(d[v]>maxd) {maxd=d[v];root=v;}
			dfs_1_(v,u);
		}
    }
    void dfs_2_(int u,int fa) {
    	for(int i=head[u];~i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(v==fa) continue;
    		int w=e[i].w;
    		dis[v]=dis[u]+w;
    		dfs_2_(v,u);
		}
	}
	inline void work_() {
		rebuild_();
		dfs_1_(1,0);
		memset(d,0,sizeof(d));maxd=0;
		dfs_1_(root,0);
		dfs_2_(root,0);
		for(int i=1;i<=n;++i) {
			printf("%d\n",max(d[co[i]],dis[co[i]]));
		}		
	}
}

void readda_() {
	n=read_();m=read_();
	for(int i=1;i<=m;++i) {
		AK[i].x=read_();AK[i].y=read_();AK[i].z=read_();
	} 
	TT::work_();
	ac::work_();
}

int main() {
	//freopen("a.txt","r",stdin);
	readda_();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值