SDZX-2022/12/24

问题 A: 真假杀光剑(allkilledsword)

时间限制: 1 Sec  内存限制: 128 MB
提交: 43  解决: 6
[提交] [状态] [命题人:HMP_Haoge]

题目描述

题目背景:

江湖上一直流传着一个叫做“黑蜻蜓”的组织的传说,他们坏事做尽,人们谈之色变。在组织内部,有一把被奉为至尊的神剑——杀光剑!!!

但是有一天,Noir 和 hbt 一人拿了一把杀光剑打起来了,并且宣称自己手中的才是真的杀光剑,他们越打越激烈,谁也不让谁,于是他们决定用一种古老的方式——取棋子,来确定杀光剑的真假。(悄悄告诉你:Noir 的杀光剑才是真的)

题目描述:

桌子上刚开始有 n 堆棋子,第i堆棋子有 a~i~ (a_i>0) 个棋子。

Noir 和 hbt 轮流操作。每次操作,可以从当前剩余的所有棋子堆中,选择出棋子数量最少的(如果有多堆棋子满足条件,则在它们中任选一堆)某一堆棋子,然后从中拿走任意数量的棋子。

要求拿走的数量不能为 0 ,不能超过这一堆所剩余的棋子数。

拿走桌子上最后一颗棋子的人获胜。

请问,在当前局面下,他们都采用最优策略,先手的 Noir 是否能够取胜,证明他手中的杀光剑才是真的?

输入

输入格式:

第一行,一个正整数 T,表示测试组数。

每组数据,第一行,一个整数 n

接下来一行,n 个整数 a~i~, 表示第 i 堆的棋子数。

输出

输出格式:

输出 T 行。

对每组数据,如果先手存在必胜策略,则输出Yes

否则输出No

样例输入 Copy

2
2
1 1
1
3

样例输出 Copy

No
Yes

提示

提示:

第一局,先手拿走第一堆的棋子,只能拿一颗。后手拿走第二堆的棋子,后手获得胜利。

第二句,先手拿走第一堆的全部棋子,先手获得胜利。

数据范围:

对30%的数据满足,n<=18,0<a_i<=10

对60%的数据满足,n<=2000,0<a_i<=1000

对100%的数据满足,0<T<=10,n<=10^4,0<a_i<=10^{18}

时间限制 1.00s

内存限制 256.00MB

这是第一次写的代码,因为找不到错误的地方就换了一种思路重写了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
long long int n;
int a[10001];
int main() {
//	freopen("allkilledsword.in","r",stdin);
//	freopen("allkilledsword.out","w",stdout);
	cin>>n;
	long long int x;
	for(int num=1; num<=n; num++) {
		int sum=0;
		cin>>x;
		for(int i=1; i<=x; i++) {
			cin>>a[i];
			if(a[i]==1)
				sum++;
		}
		if(x==1) {
			cout<<"Yes"<<endl;
			break;
		}
		int ans=sum%2;
		if(sum==x && ans==0) {
			cout<<"No"<<endl;
		} else if(ans==1 && x>=2) {
			cout<<"No"<<endl;
		} else {
			cout<<"Yes"<<endl;
		}
	}
	return 0;
}

AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[10001];
long long b[10001];
bool c[10001];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int sum=0;
        cin>>a[i];
        for(int j=1;j<=a[i];j++)
        {
            cin>>b[j];
            {
                if(b[j]==1) sum++;
            }
        }
        if(a[i]==2&&b[1]==1&&b[2]==1) a[i]=0;
        if(a[i]==1) c[i]=1;
        if(a[i]>=2&&sum%2==0) c[i]=1;
        if(a[i]>=2&&sum%2!=0) c[i]=0;
    }
    for(int i=1;i<=n;i++)
    {
        if(c[i]==0) cout<<"No"<<endl;
        else cout<<"Yes"<<endl;
    }
    return 0;
}


问题 B: 合并毛毛(HBT)

时间限制: 2 Sec  内存限制: 512 MB
提交: 65  解决: 2
[提交] [状态] [命题人:HMP_Haoge]

题目描述

题目背景

不需要,你只需要高呼“毛毛!!!”

题目描述

在一个果园里,noir已经将所有的毛毛打了下来,而且按毛毛的不同种类分成了不同的堆。noir决定把所有的毛毛合成一堆。

每一次合并,noir可以把两堆毛毛合并到一起,消耗的体力等于两堆毛毛的重量之和。可以看出,所有的毛毛经过 n-1 次合并之后, 就只剩下一堆了。noir在合并毛毛时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些毛毛搬回家,所以noir在合并毛毛时要尽可能地节省体力。假定每个毛毛重量都为 1 ,并且已知毛毛的种类 数和每种毛毛的数目,你的任务是设计出合并的次序方案,使noir耗费的体力最少,并输出这个最小的体力耗费值。

例如有 3 种毛毛,数目依次为 1 , 2 , 9 。可以先将 1 、 2 堆合并,新堆数目为 3 ,耗费体力为 3 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12 ,耗费体力为 12 。所以noir总共耗费体力 =3+12=15 。可以证明 15 为最小的体力耗费值。

输入

输入格式

共两行。 第一行是一个整数 n(1\leq n\leq 5000) ,表示毛毛的种类数。

第二行包含 n 个整数,用空格分隔,第 i 个整数 a_i(1\leq a_i\leq 20000) 是第 i 种毛毛的数目。

输出

输出格式

一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2^{31} 。

样例输入 Copy

3
1 2 9

样例输出 Copy

15

提示

提示

对于 30\% 的数据,保证有 n \le 10:

对于 50\% 的数据,保证有 n \le 1000;

对于全部的数据,保证有 n \le 5000。

提示:hack数据是800000的,可以过不了,是给priority_queue准备的。

水题一道没什么好说的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
int n;
int a[100001];
int main() {
	long long int ans=0;
//	freopen("maomao.in","r",stdin);
//	freopen("maomao.out","w",stdout);
	cin>>n;
	for(int i=1; i<=n; i++) cin>>a[i];
	sort(a+1,a+n+1);
	for(int i=1;i<=n-1;i++){
		ans=ans+a[i]+a[i+1];
		a[i+1]+=a[i];
		sort(a+1+i,a+1+n);//累加
	}
	cout<<ans;
	return 0;
}


问题 C: 毛毛塔(maomaota)

时间限制: 1 Sec  内存限制: 512 MB
提交: 50  解决: 19
[提交] [状态] [命题人:HMP_Haoge]

题目描述

题目背景

直达毛毛路·弔王历险记

题目描述

在Noir的帮助下,弔王成功收集到了宝贵的数据,他来到了传说中连接通天路的毛毛山。但是这距离通天路仍然有一段距离,但是弔王突然发现他没有地图!!!但是幸运的是,他在山脚下发现了一个宝箱。根据经验判断,地图应该就在其中!在宝箱上,有三根柱子以及在一根柱子上的n个圆盘。弔王在经过很长时间判断后,觉得这就是毛毛塔!但是移动是需要时间的,所以弔王必须要通过制造延寿药水来完成这项任务。现在,请你告诉弔王需要多少步完成,以便他造足够的延寿药水.。时限1s。

毛毛塔(汉诺塔):

有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子C上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,请问至少需要多少次移动

输入

输入格式

一个数n,表示有n个圆盘

输出

输出格式

一个数s,表示需要s步。

样例输入 Copy

样例输入 #1
31
样例输入 #2
15

样例输出 Copy

样例输入 #1
2147483647
样例输入 #2
32767

提示

提示

对于 30\% 的数据n<=60

对于所有数据n<=15000

#include<bits/stdc++.h>
using namespace std;
int n,l,i,a[10000];
void p() {
	for(int i=1; i<=l; i++)a[i]*=2;
	for(int i=1; i<=l; i++)
		if(a[i]>=10) {
			a[i+1]++;
			a[i]-=10;
		}
	if(a[l+1]>0)l++;
}
int main() {
	cin>>n;
	a[1]=1;
	l=1;
	for(i=0; i<n; i++)p();
	for(i=l; i>1; i--)cout<<a[i];
	cout<<a[1]-1;
	return 0;
}

//重写为什么 is 卡密? 
//写完才发现这道题这么简单,我怕是个小可爱
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//#include<cmath>
//#include<map>
//#include<algorithm>
//using namespace std;
//const int N=9999;
//string s1,s2;
//int sum;
//int a[N],b[N],c[N];
//int main() {
	freopen("maomaota.in","r",stdin);
	freopen("maomaota.out","w",stdout);
//	int n;
//	cin>>n;
//	a[1]=1;
//	for(int i=1; i<=n; i++) {
//		sum=0;
//		for(int j=1; j<=n; j++) {
//			if(a[j]!=0 || a[j+1]!=0 || a[j+2]!=0 || a[j+3]!=0 || a[j+4]!=0 || a[j+5]!=0) {
//				a[j]*=2;
//				sum++;
//			} else break;
//		}
//		for(int j=1;j<=sum+1;j++) {
//			if(a[j]>=10) {
//				int x=a[j]/10;
//				a[j+1]=a[j+1]+x;
//				a[j]%=10;
//			}
//		}
//	}
//	int num=0;
//	a[1]-=1;
//	for(int i=n; i>=1; i--) {
//		if(num==0 && a[i]==0) {
//			continue;
//		} else if(num==0 && a[i]!=0) {
//			num=1;
//			cout<<a[i];
//		} else if(num==1 && a[i]==0) {
//			cout<<a[i];
//		} else {
//			cout<<a[i];
//		}
//	}
//	return 0;
//}

问题 D: 奶油蛋糕( LH )

时间限制: 1 Sec  内存限制: 512 MB
提交: 43  解决: 7
[提交] [状态] [命题人:HMP_Haoge]

题目描述

题目背景


早餐时间过后,小不点们都前往操场接受基础训练课程, Noir 便趁机占据厨房了。 他在军服上披围裙,头上绑三角巾,还将清早从市场采买回来的大量材料摆到桌上。 接着, Noir 烤了大量的奶油蛋糕。

Noir 把奶油蛋糕摆放到桌子上,弔王闻到了蛋糕的香味,迫不及待地扑到了餐桌前享受着这份饕餮盛宴,然而蛋糕的制作,似乎还差了那么最后一步…… “等一等哦,我还没有挤上奶油呢。” Noir 说着,拿起了裱花袋。

可饥肠辘辘的弔王哪里等得起全部的奶油都给挤好? 正当 Noir 还在忙着挨个给蛋糕挤上白花花的奶油的时候,弔王已经偷偷的拿起了一块蛋糕……

题目描述

在桌子上的蛋糕可以看作是一个无限大的平面直角坐标系,每一个蛋糕都位于坐标系的整点上。

每一分钟, Noir 会给每个蛋糕都涂上若干层奶油,规则如下:如果蛋糕连续第 i 次没有被弔王吃到,那么就会在蛋糕上挤上 i 层奶油。

每次在 Noir 挤完所有蛋糕的奶油后,弔王会拿起一块蛋糕,把这个蛋糕上的奶油给吃掉一层。特别的,如果弔王吃掉了蛋糕上的一层奶油, Noir 马上会贴心的再次给这个蛋糕补上一层,且不计入连续没有被吃到的次数里(即下一次的 i 依旧为 1 )。

由于蛋糕太多,弔王实在不知道从何下手,所以他决定按照移动的吃法进行试吃。 总共 m 个分钟,弔王的吃蛋糕序列可以用一个长度为 m 的字符串表达。第 t 个字符可能为 N,S,W,E分别表示弔王在第 t+1 分钟会吃掉第 t 分钟吃掉蛋糕的上,下,左,右方位的蛋糕。 弔王第 1 个分钟会拿起位于点 (x,y) 的蛋糕,因为蛋糕目前没有被挤上奶油,所以弔王既不会进行试吃, Noir 也不会立刻给他补上奶油。

弔王想知道在 m 分钟后,这些蛋糕在最后都还剩多少层奶油。

本题中的上和右分别表示 y 轴正方向和 x 轴正方向。

输入

输入格式

第一行四个正整数 n,m,x,y,含义如题面所示,其中 x,y 表示横纵坐标,不是数组下标。 第二行一个长度为 m 的字符串,表示弔王的移动序列。

输出

输出格式

共n 行,每行 n 个数,第 i 行的第 j 个数表示坐标 (j,n-i+1) 上的灰的数量

样例输入 Copy

样例1:
5 4 1 1
NENW
样例2:
7 14 1 1
NENENENENESSSS
样例3:
10 70 2 2
NWSNSNNNSNNSSNNSENNNNEESNWSESESSWENNSEWESWWWESEEESENNSENWNESNWSNNNEESS
样例4:
5 4 2 1
NENW

样例输出 Copy

样例1:
10 10 10 10 10
10 10 10 10 10
10 6 10 10 10
4 4 10 10 10
6 10 10 10 10
样例2:
105 105 105 105 105 105 105
105 105 105 105 55 61 105
105 105 105 49 51 69 105
105 105 51 49 105 79 105
105 61 55 105 105 91 105
79 69 105 105 105 105 105
91 105 105 105 105 105 105
样例3:
2485 2485 2485 2485 2485 2485 2485 2485 2485 2485
2485 1407 1205 1267 2485 2485 2485 2485 2485 2485
2485 1435 1281 1167 2485 2485 2485 2217 2281 2347
2485 1465 2485 1255 1041 2485 2485 2155 2485 2415
1557 1497 2485 2485 969 1177 2485 1733 1807 2485
1471 1531 1315 907 935 1267 2485 1473 1647 2485
1631 2485 2485 1357 1381 1407 1435 1499 1645 2485
2021 2347 2485 2485 2485 2485 1465 1497 2485 2485
2087 2415 2485 2485 2485 2485 2485 2485 2485 2485
2485 2485 2485 2485 2485 2485 2485 2485 2485 2485
样例4:
10 10 10 10 10
10 10 10 10 10
10 10 6 10 10
10 4 4 10 10
10 6 10 10 10

提示

提示

本题 y 轴朝上,x 轴朝右,样例输出中的左下角表示 (1,1),第一分钟弔王在初始点处,第二分钟移动到相应的位置,第 m+1 分钟移动到最后一个点,但是总共只有 m 分钟,因此最后一个点不受移动的影响


样例 1 解释:

弔王的移动路径为 (1,1)\rightarrow(1,2)\rightarrow(2,2)\rightarrow(2,3)\rightarrow(1,3),共 4 分钟。

对于第 1 分钟,(1,1) 奶油层数不变,其余点被挤上了 1 层奶油。

对于第 2 分钟,(1,2) 奶油层数不变,(1,1) 被挤上了 1 层奶油,其余点挤上 2 层奶油。

对于第 3 分钟,(2,2) 奶油层数不变,(1,1) 挤上 2 层奶油,(1,2) 挤上 1 层奶油,其余点挤上 3 层奶油。

对于第 4 分钟,(2,3) 奶油层数不变,(1,1) 挤上 3 层奶油,(1,2) 挤上 2 层奶油,(2,2) 挤上 1 层奶油,其余点挤上 4 层奶油。

注意最后弔王移动到了 (1,3),但是时间只有 4 分钟,所以实际上不会对 (1,3) 造成影响。初始点不一定在 (1,1)。

1\le n\leq 50,1\leq m\le 1000。

这是第一次写的代码,输出有问题,老是没有逆序,于是有换了一种思路重新写了一遍。。。

(草

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
int n,m,x,y;
char a[1001];
int ans[1001][1001],num[1001][1001];
int main() {
//	freopen("zhegeeasy.in","r",stdin);
//	freopen("zhegeeasy.out","w",stdout);
	cin>>n>>m>>y>>x;
	for(int i=1; i<=m; i++) cin>>a[i];
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			num[i][j]=1;
			ans[i][j]=1;
		}
	}
	num[x][y]=0;
	ans[x][y]=0;

	for(int t=2; t<=m; t++) {
		if(a[t-1]=='N')	y+=1;
		if(a[t-1]=='S')	y-=1;
		if(a[t-1]=='W')	x-=1;
		if(a[t-1]=='E')	x+=1;

		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				num[i][j]++;
			}
		}
		num[x][y]=0;
		for(int i=n; i>=1; i--) {
			for(int j=1; j<=n; j++) {
				ans[i][j]+=num[i][j];
			}
		}
	}

	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			cout<<ans[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}
/*

5 4 2 1
NENW

*/

#include<bits/stdc++.h>
#define N 5001
using namespace std;

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<<3)+(x<<1)+(c^48);
		c=getchar();
	}
	return x*f;
}
int a[N][N],b[N][N];
int main() {	
	int n=read(),m=read(),y=read(),x=read();
	memset(a,0,sizeof(a));
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			b[i][j]=1;
	x=n-x+1;
	
	while(m--) {
		char c;
		cin>>c;
		b[x][y]=0;
		for (int i=1; i<=n; i++)
			for (int j=1; j<=n; j++)
				a[i][j]+=b[i][j];
		if (c=='N') x--;
		if (c=='S') x++;
		if (c=='W') y--;
		if (c=='E') y++;
		for (int i=1; i<=n; i++)
			for (int j=1; j<=n; j++)
				b[i][j]++;
	}
	for (int i=1; i<=n; i++) {
		for (int j=1; j<=n; j++)
			cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值