2.14 比赛题解

总体概述

难度

  1. C 东方绯想天 入门
  2. E 东方鬼形兽 入门
  3. D 东方辉针城 入门
  4. A 东方红魔乡 普及-
  5. B 东方永夜抄 普及-
  6. G 东方茨歌仙 普及
  7. F 东方幻想麻雀 普及
  8. H 东方铃奈庵 普及+

是不是很水?没到300pts的非 20 级在役选手面壁思过!

下面按题目顺序进行讲解。

A 东方红魔乡

原题出自

2020牛客NOIP赛前集训营-普及组(第四场) B

想一下对于大小姐和二小姐的必胜策略。

对于大小姐

大小姐拿偶数个。首先,能一次性拿走的偶数个堆石子就一次性拿走,不给对方机会。其次,如果只有一堆偶数个石子,那么将其直接拿走就能获得胜利。

对于二小姐

二小姐拿奇数个。对于一堆奇数个石子,全部拿走不给对方机会。对于一堆偶数个石子,把它拆成 1 和 2n-1 (总 2n 个),这样可以保证必胜。

也就是说,如果只有一堆偶数个棋子,那么可以保证大小姐胜利。否则二小姐可以把任意一堆石子变成 1 ,导致大小姐不能获胜。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
const int N=1000005;
inline int read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
int n,a;
int main() {
//	freopen("hmx.in","r",stdin);
//	freopen("hmx.out","w",stdout);
	int t=read();
	while(t--) {
		n=read();
		if(n==1) {
			a=read();
			if(a&1) puts("NO");
			else puts("YES");
		}
		else {
			while(n--) a=read();
			puts("NO");
		}
	}
	return 0;
}

B 东方永夜抄

原题出自

ZROI 2020 普及五连测 Day4 T1

很容易猜到一个结论,排序以后,直接按照顺序两两配对,而这确实是对的。

小证明:对于一个较小的数,与较大的数匹配一定比与更大的数匹配更优,这样会使差的绝对值的和更小。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
const int N=200005;
inline int read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
int a[N];
int main() {
	//freopen("yyc.in","r",stdin);
	//freopen("yyc.out","w",stdout);
	int n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);
	int ans=0;
	for(int i=1;i<n;i+=2) {
		ans+=a[i+1]-a[i];
	}
	printf("%d",ans);
	return 0;
}

C 东方绯想天

原题出自

@ahawzlc

设普通桃子个数为 \(m\) 个。

\[V_{仙桃总}=\frac{4}{3}n\pi a^3 \]

\[V_{普通总}=\frac{4}{3}m\pi b^3 \]

\[V_{仙桃总}=V_{普通总} \]

\[\frac{4}{3}n\pi a^3=\frac{4}{3}m\pi b^3 \]

\[m=\frac{na^3}{b^3} \]

根据题目要求,使用“进位法”取整。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=200005;
inline ll read() {
	ll sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
ll n,a,b;
int main() {
//	freopen("fxt.in","r",stdin);
//	freopen("fxt.out","w",stdout);
	n=read(),a=read(),b=read();
	ll now=n*a*a*a,ans;
	ans=now/(b*b*b);
	if(b*b*b*ans==now) printf("%lld",ans);
	else printf("%lld",ans+1);
	return 0;
}

D 东方辉针城

原题出自

@ahawzlc

简要分析可得,只要点的高度大于下落时间 \(t\) ,那么这个点就可以被收取。(所以甚至一维数组都不用)

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
const int N=10005;
inline int read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
int x[N],y[N],ans;
int main() {
//	freopen("hzc.in","r",stdin);
//	freopen("hzc.out","w",stdout);
	int n=read(),m=read(),q=read(),t=read();
	for(int i=1;i<=q;i++) {
		x[i]=read(),y[i]=read();
		if(y[i]>t) ans++;
	}
	printf("%d",ans);
	return 0;
}

E 东方鬼形兽

原题出自

@ahawzlc (不过似乎与别的题撞了)

以样例为例解释题目:

样例1 最少:
1_1

样例1 最多:
1_2

也就是说,最少时,每个方块至少独自承担了对主视图或对左视图的一个贡献,最多时的情况就是在最少时的情况把所有空间补全。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
const int N=200005;
inline ll read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
int main() {
//	freopen("gxs.in","r",stdin);
//	freopen("gxs.out","w",stdout); 
	ll n=read(),m=read(); 
	printf("%lld %lld",max(n,m),1ll*n*m);
	return 0;
}

F 东方幻想麻雀

原题来自

@ahawzlc

字符串读入、存储、处理。没有幺九牌就是断幺九、有三个及以上暗刻就是三暗刻,只有一种颜色就是清一色。

具体实现参见代码

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
const int N=200005;
inline int read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
char c;
int mah[4][10],now,num;
bool z=0,dyj,sak,qys,m,p,s;
int main() {
	for(int i=1;i<=18;i++) {
		scanf("%c",&c);
		if('0'<=c&&c<='9') mah[now][c-'0']++;
		else now++;
	}
	for(int j=1;j<=7;j++) {
		if(mah[3][j]) {
			z=1;break;
		}
	}
	if(mah[0][1]==0&&mah[0][9]==0&&mah[1][1]==0&&mah[1][9]==0&&mah[2][1]==0&&mah[2][9]==0&&!z) dyj=1;
	for(int i=0;i<=3;i++) {
		for(int j=1;j<=9;j++) {
			if(mah[i][j]>=3) num++; 
			if(mah[0][j]) m=1;
			if(mah[1][j]) p=1;
			if(mah[2][j]) s=1;
		}
	}
	if(num>=3) sak=1;
	if((m&&!p&&!s&&!z)||(p&&!m&&!s&&!z)||(s&&!m&&!p&&!z)||(z&&!m&&!p&&!s)) qys=1;
	if(dyj) printf("1");
	if(sak) printf("2");
	if(qys) printf("3");
	if(!dyj&&!sak&&!qys) printf("NO"); 
	return 0;
}

G 东方茨歌仙

原题出自

ZROI 2020 普及五连测 Day3 T1

你以为这只是个简单的数组模拟?ko no 离线处理 da!

直接使用数组模拟只有 60 pts,因为数组下标范围过于大,装不下。

所以考虑离线处理。

对于每一个查询,向前找最近的该点的修改,找不到为0。\(O(n^2)\)

原题作者说似乎可以使用二分优化,不知道这次有没有。\(O(log n)\)

当然可以直接用 map 。\(O(n)\)

代码 \(O(n^2)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
const int N=2005;
inline int read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
pi q[N];
int main() {
//	freopen("cgx.in","r",stdin);
//	freopen("cgx.out","w",stdout);
	int n=read(),m=read();
	for(int i=1;i<=n;i++) {
		int opt=read();
		if(opt==1) {
			int x=read(),y=read();
			q[i]=make_pair(x,y);
		}
		if(opt==2) {
			int x=read();
			bool ok=0;
			for(int j=i-1;j>=1;j--) {
				if(q[j].F==x) {
					printf("%d\n",q[j].S);
					ok=1;
					break;
				}
			}
			if(!ok) puts("0");
		}
	}
	return 0;
}

H 东方铃奈庵

原题出自

@ahawzlc

部分分:

30pts 乱搞
第一个 20pts 输出 \(k\)
第二个 20pts 堆优 bfs
100pts 结构体堆优 bfs

100pts

因为小铃认为越近的点价值越高,所以bfs。
因为需要求最大价值,所以堆优。
因为同时需要最小花费,所以结构体,重定义小于号。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define re register
#define pi pair<int,int>
#define F first
#define S second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
const int N=1000005;
inline int read() {
	int sum=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		sum=(sum<<3)+(sum<<1)+ch-'0';
		ch=getchar();
	}
	return sum*w;
}
struct node {
	int u,w,c;
};
bool operator < (const node &x,const node &y) {
	if(x.w==y.w) return x.c>y.c;
	return x.w<y.w;
}
priority_queue<node> q;
int n,k,w[N],c[N];
ll ans;
int cnt,h[N],nxt[N],to[N],rd[N];
void add(int x,int y) {
	nxt[++cnt]=h[x],to[cnt]=y,h[x]=cnt;
}
bool vis[N];
void pro_bfs() {
	int tot=0;
	node p;
	p.c=p.w=0,p.u=1;
	q.push(p);
	while(!q.empty()) {
		int u=q.top().u;
		q.pop();
		tot++;
		ans+=1ll*c[u];
		vis[u]=1;
		if(tot==k+1) return; 
		for(int i=h[u];i;i=nxt[i]) {
			int v=to[i];
			if(vis[v]) continue;
			p.c=c[v],p.w=w[v],p.u=v;
			q.push(p);
		}
	}
	return;
}
int main() {
//	freopen("lna.in","r",stdin);
//	freopen("lna.out","w",stdout);
	n=read(),k=read();
	for(int i=1;i<=n;i++) c[i]=read();
	for(int i=1;i<=n;i++) w[i]=read();
	for(int i=1;i<n;i++) {
		int x=read(),y=read();
		add(x,y);
		add(y,x);
	}
	pro_bfs();
	printf("%lld",ans);
	return 0;
}
posted @ 2021-02-13 22:11  ahawzlc  阅读(48)  评论(1编辑  收藏  举报