Codeforces Round 883 (Div. 3) A~G

比赛链接:Dashboard - Codeforces Round 883 (Div. 3) - Codeforces

目录

A. Rudolph and Cut the Rope

B. Rudolph and Tic-Tac-Toe

C. Rudolf and the Another Competition

D. Rudolph and Christmas Tree

E. Rudolf and Snowflakes 

F. Rudolph and Mimic

G. Rudolf and CodeVid-23


A. Rudolph and Cut the Rope

题意:给你n个绳子高度和绳子长度,问你至少需要割掉几根绳子才能得到糖果。

思路:若绳子高度比长度长则糖果会被吊着到不了地面,所以比较绳子长度和高度大小即可。

代码:

void solve() {
	int n,x,y,ans=0;
	cin>>n;
	FOR(1,n) {
		cin>>x>>y;
		ans+=(x>y);
	}
	cout<

B. Rudolph and Tic-Tac-Toe

题意:给你一个已经3*3的已经布置好的棋盘,横着连一块竖着连一块或者斜着连一块那个人就赢了,问你谁会赢。

思路:按照题意模拟即可。

代码:

void add(char c) {
	if(c=='X')x++;
	else if(c=='O')y++;
	else if(c=='+')z++;
}
void solve() {
	x=y=z=0;
	for(int i=1; i<=3; i++)
		for(int j=1; j<=3; j++)
			cin>>a[i][j];
	for(int i=1,j=1; i<=3; i++) {
		if(a[i][j]==a[i][j+1]&&a[i][j+1]==a[i][j+2]) add(a[i][j]);
		if(a[j][i]==a[j+1][i]&&a[j+1][i]==a[j+2][i]) add(a[j][i]);
	}
	if(a[1][1]==a[2][2]&&a[3][3]==a[1][1]) add(a[1][1]);
	if(a[3][1]==a[2][2]&&a[3][1]==a[1][3]) add(a[1][3]);
	if(x)cout<<"X"<

C. Rudolf and the Another Competition

题意:给你n个m行的出题时间,比赛在第h分钟罚时结束,每做一个题的罚时会累加到后面,你是第一个人,问你的排名是多少(若有人和你并列,你的排名则在那个人的前面)。

思路:出题快的先写,排序模拟一下即可。记得开long long,该题会爆int(我已经#define int long long 了)。

struct st {
	int num,t,id;
};
bool cmp(st a,st b) {
	if(a.num!=b.num)return a.num>b.num;
	if(a.t!=b.t)return a.tans;
	int n,m,h,res=0;
	cin>>n>>m>>h;
	for(int i=1;i<=n;i++) {
		vectorv;
		for(int j=1;j<=m;j++) {
			int x;
			cin>>x;
			v.push_back(x);
		}
		int sum=0,t=0,num=0;
		sort(v.begin(),v.end());
		for(auto x:v) {
			if(sum+x>h)break;
			num++,sum+=x,t+=sum;
		}
		ans.push_back({num,t,i});
	}
	sort(ans.begin(),ans.end(),cmp);
	for(auto x:ans) {
		res++;
		if(x.id==1)break;
	}
	cout<

D. Rudolph and Christmas Tree

题意:给你n个等腰三角形的底和高,还有它在坐标轴上的高度,问你最后这几个三角形的总面积是多少(可能会重叠)。

思路:若该三角形是第一个三角形或者它没和上一个三角形重叠,它对答案的贡献就为它自己的面积;若它与上一个三角形重叠了,那么未重叠部分就是梯形,这个三角形对答案的贡献为梯形面积。梯形面积为(上底+下底)*高/2,上底和高都能通过相似的比例求出来,将每个三角形的贡献求出来即可。

void solve() {
	int n;
	double d,h;
	double ans=0;
	cin>>n>>d>>h;
	for(int i=1; i<=n; i++)cin>>a[i];
	sort(a+1,a+n+1,greater());
	for(int i=1; i<=n; i++) {
		if(i==1||a[i]+h<=a[i-1]) {
			ans+=d*h/2;
			continue;
		}
		double k=(a[i-1]-a[i]);//高
		double dd=d*((h-k)/h);//上底
		ans+=(dd+d)*k/2;
	}
	cout<

E. Rudolf and Snowflakes 

题意:给你一个n,问你是否能够找到(1-q^k)/(1-q)(等比数列前n项和)恰好等于n,其中q,k为自定义,q>=2,k>=3。

思路:当q小于1e6时,直接预处理判断即可,而当q大于1e6时时候,若k等于4,则(1-q^4)/(1-q)>1e18,超过了n范围了,所以当q>1e6时k只可能等于3,此时只需要判断q^2+q+1=n,是否存在整数根即可(预处理会爆long long,记得开__int128)

const int maxn = 1e6 + 5;
unordered_mapmp;
void solve() {
	int n;
	cin>>n;
	if(mp[n]) {
		yes;
		return;
	}
	int k=4*n-3;
	int q=sqrt(k);
	if(q*q==k&&n!=1&&n!=3)yes;
	else no;
}
signed main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	for(int i=2; i<=maxn; i++) {
		__int128 k=i*i*i;
		for(__int128 j=1+i+i*i; j<=1e18; j+=k,k*=i)mp[j]=true;
	}
	int _;
	cin >> _;
	while (_--)
		solve();
	return 0;
}

F. Rudolph and Mimic

题意:Codeforces Round 883 (Div. 3) A~G_第1张图片

思路:因为模仿者不能连续超过两个阶段保持同一个值, 所以在不超过两步的时候必然会有一个值x的个数会增加,换句话说就是模仿者变成了x,所以模仿者就在这些x之中。接下来我们把值不等于x的值给去除,在不超过两步的时候又必然有个值会变化,所以在剩下来的值中,不同于原先的x的即是模仿者。

代码:

map>mp1,mp2;
int n,x,f,ff;
void sol() {
	cout<<"- 0"<>x,mp2[x].push_back(i);//存储输入元素及其下标
	for(int i=1; i<=9; i++) {
		if(mp2[i].size()>mp1[i].size()) {
			f=i;//f记录的是第一次模仿者变成了什么数字
			return;
		}
	}
}
void sol2() {
	for(int i=1; i<=n; i++) {
		cin>>x;
		if(x!=f)ff=i;//模仿者改变了所以和其它元素的值不同,ff记录模仿者下标。
	}
}
void solve() {
	f=0,ff=0;
	cin>>n;
	for(int i=1; i<=9; i++)mp1[i].clear();
	for(int i=1; i<=n; i++)cin>>x,mp1[x].push_back(i);
	while(!f) sol();

	cout<<"- "<

G. Rudolf and CodeVid-23

题意: Codeforces Round 883 (Div. 3) A~G_第2张图片

Codeforces Round 883 (Div. 3) A~G_第3张图片

 思路:可以注意到n<=10,所以我们可以将二进制的字符串转换为10进制的数字,方便计算它们的贡献。设一开始的状态为a,一个药的药效为b,它的副作用为c,则a用了这个药后会变为(a&~b)|c。~为取反的意思,1变0,0变1。这是因为b中的1会使得a中相同位的1变成0(也就是治病),并且b中的0对于a没有影响,所以要用&且取反;而c中的1会使得a中相同位的0变成1(也就是副作用导致生病),并且c中的0对于a没有影响,所以要用 |。

然后将每个药需要消耗的天数作为边权,(a&~b)|c作为转移公式,跑一遍最短路即可。若dis[0]>=inf则说明跑不到0(没病的情况),输出-1;反之输出dis[0]。

代码:

int get(string s){
	int n=s.size(),sum=0,now=1;
	for(int i=n-1;i>=0;i--){
		sum+=now*(s[i]=='1');
		now*=2;
	}
	return sum;
}
void solve() {
	mem(vis,0);
	mem(dis,inf);
	int n,m,now;
	string s,s1,s2;
	cin>>n>>m>>s;
	now=get(s);
	dis[now]=0;
	for(int i=1;i<=m;i++){
		cin>>d[i]>>s1>>s2;
		a[i]=get(s1),b[i]=get(s2);
	}
	priority_queue,greater>q;
	q.push({0,now});
	while(!q.empty()){
		auto k=q.top();
		q.pop();
		if(vis[k.second])continue;
		vis[k.second]=true;
		for(int i=1;i<=m;i++){
			int temp1=(k.second&~a[i])|b[i];
			int temp2=dis[k.second]+d[i];
			if(dis[temp1]>temp2){
				dis[temp1]=temp2;
				q.push({temp2,temp1});
			}
		}
	}
	if(dis[0]>=inf)cout<<-1<

你可能感兴趣的:(codeforces题解,算法,数据结构)