NOIP模拟赛

正题

      首先,没看懂题目之前是自闭的。

      看懂题目之后基本都能想出正解。

      第一题:

      A和B两个人,给出他们俩的坐标,如果A和B在同一行,那么A受到一点伤害,A可以放子弹,如果B碰到子弹,B受到一点伤害。

      两种操作,所有子弹向上,下,左,右移动;或者B向上,下,左,右移动。

      暴力即可,注意是在平面直角坐标系上。

#include
#include
#include
#include
using namespace std;

int Case;
int n,m,q;
int ax,ay,bx,by;
int sx,sy;
char s[10];
struct node{
	int x,y;
}p[1010];
bool tf[110][110];
int ans1,ans2;

int main(){
	scanf("%d",&Case);
	int t=0;
	int x,y;
	scanf("%d %d",&n,&m);
	scanf("%d %d",&ax,&ay);	
	scanf("%d %d",&bx,&by);
	sx=bx,sy=by;
	ans1=ans2=0;
	scanf("%d",&q);
	memset(tf,false,sizeof(tf));
	for(int i=1;i<=q;i++){
		if(ax==bx) ans1++;
		if(tf[bx][by]) ans2++;
		scanf("%s",s);
		if(s[0]=='D'){
			scanf("%d %d",&x,&y);
			tf[x][y]=false;
		}
		else if(s[0]=='I'){
			scanf("%d %d",&x,&y);
			tf[x][y]=true;
		}
		else if(s[0]=='M' && s[1]=='A'){
			t=0;
			scanf("%s",s);
			for(int a=1;a<=n;a++)
				for(int b=1;b<=m;b++)
					if(tf[a][b]) p[++t]=(node){a,b};
			memset(tf,false,sizeof(tf));
			if(s[0]=='U') for(int a=1;a<=t;a++) p[a].y++;
			if(s[0]=='D') for(int a=1;a<=t;a++) p[a].y--;
			if(s[0]=='L') for(int a=1;a<=t;a++) p[a].x--;
			if(s[0]=='R') for(int a=1;a<=t;a++) p[a].x++;
			for(int a=1;a<=t;a++) if(p[a].x>=1 && p[a].x<=n && p[a].y>=1 && p[a].y<=m) tf[p[a].x][p[a].y]=true;
		}
		else if(s[0]=='M' && s[1]=='B'){
			scanf("%s",s);
			if(s[0]=='U') by++;
			if(s[0]=='D') by--;
			if(s[0]=='L') bx--;
			if(s[0]=='R') bx++;
			if(bx>n || bx<1 || by>m || by<1) bx=sx,by=sy;
		}
	}
	printf("%d\n%d\n",ans2,ans1);
}

      第二题:

      n个点,有k个点是关键点,构造全排列,对于每个排列的费用是排列中相邻两个点路径的距离之和。

      求费用的期望。

      从a到b的距离会被算(k-1)!那么多次,所以我们对于每个点求一遍这个点到其他点的距离和,加起来乘上(k-1)!即可。

      最后除以k!,其实就相当于除以一个k。

#include
#include
#include
#include
using namespace std;

struct edge{
	int y,next,c;
}s[2000010];
int first[1000010],len=0;
int t;
int n,k;
long long tot[1000010];
long long in[1000010],out[1000010];
int p[1000010];
long long mod=998244353;

void ins(int x,int y,int c){
	len++;
	s[len]=(edge){y,first[x],c};first[x]=len;
}

void dfs_1(int x,int fa){
	for(int i=first[x];i!=0;i=s[i].next){
		int y=s[i].y;
		if(y==fa) continue;
		dfs_1(y,x);
		tot[x]+=tot[y];
		in[x]+=in[y]+tot[y]*s[i].c;
	}
}

void dfs_2(int x,int fa){
	for(int i=first[x];i!=0;i=s[i].next){
		int y=s[i].y;
		if(y==fa) continue;
		out[y]=out[x]+in[x]-(in[y]+tot[y]*s[i].c)+(k-tot[y])*s[i].c;
		dfs_2(y,x);
	}
}

long long ksm(long long x,long long t){
	long long tot=1;
	while(t){
		if(t%2) (tot*=x)%=mod;
		(x*=x)%=mod;
		t/=2;
	}
	return tot;
}

int main(){
	scanf("%d",&t);
	scanf("%d",&n);
	int x,y,c;
	for(int i=1;i<=n-1;i++){
		scanf("%d %d %d",&x,&y,&c);
		ins(x,y,c);ins(y,x,c);
	}
	scanf("%d",&k);
	for(int i=1;i<=k;i++){
		scanf("%d",&x);
		p[i]=x;
		tot[x]=1;
	}
	dfs_1(1,0);
	dfs_2(1,0);
	long long ans=0;
	for(int i=1;i<=k;i++) (ans+=in[p[i]]+out[p[i]])%=mod;
	printf("%lld",ans*ksm(k,mod-2)%mod); 
}

      第三题:

      每个点有一种颜色,共有四种颜色,A能到B当且仅当A到B的路径上每一个周期(4个为一周期)颜色不同。

      求一个点,使得这个点到k个点的距离最小。

      状态压缩+bfs即可。

#include
#include
#include
#include
#include
using namespace std;

struct edge{
	int y,next;
}s[400010];
int first[50010],len=0;
int type[50010];
char ch[50010];
int tf[50010][16];
int mmax[50010],tot[50010];
int T;
int n,m,k;
int p[15];
struct node{
	int x,S,t;
};
queue f;

void ins(int x,int y){
	len++;
	s[len]=(edge){y,first[x]};first[x]=len;
}

void bfs(int st){
	memset(tf,63,sizeof(tf));
	f.push((node){st,1<

      总的来说,这次比赛挺简单的,第一题和第三题都打了出来,第二题思维深度也不高。

      注意细节吧。

你可能感兴趣的:(NOIP模拟赛)