CUC Personal Training 1.0

CUC Personal Training 1.0

首先这次的题目选的都是CF700-1300的题目,设计内容主要有贪心、构造、模拟、二分以及一些简单的数学问题(数论的那个题其实用不到什么数论知识QAQ).然后自我反思一下:题目的选取不够合理,后面放的几道1300的题莫名其妙是水题…,一般模拟就都可以过。

A.Array with Odd Sum(CF800)

题目描述:题目给出了了一个含有n个数的数组a,现在可以对该数组做出一种操作:将数组中的某一个元素用数组中的其他元素替代,现在问能否构造出一个元素和为奇数的数组。

解题思路:如果本身数组的和就已经是奇数了,那么自然满足条件,其次如果数组中既有奇数又有偶数,那么我们总可以找到一个数组满足条件。

AC代码(From chocolate~):

#include<bits/stdc++.h>
#pragma warning(disable:4996)
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		int sum=0;
		int flag0=0, flag1=0;
		int a[2005];
		cin >> n;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i];
			sum += a[i];
			if (a[i] % 2 == 0)flag0 = 1;
			else flag1 = 1;
		}
		if (sum % 2 == 0) {
			if (flag0&&flag1)cout << "YES"<<endl;
			else cout << "NO"<<endl;
		}
		else cout << "YES"<<endl;

	}
	return 0;
}

B.Display The Number(CF900)

题目描述:有一个大的电子屏幕,可以显示998244353个十进制数字。数字的显示方式与不同的电子闹钟相同:每个数字的位置由7个部分组成,可以打开和关闭,组成不同的数字。下图描述了如何显示所有10位小数:

可以看到,不同的数字可能需要打开不同数量的段。例如,如果你想显示1,你必须打开屏幕的2段,如果你想显示8,显示数字的某个地方的所有7段都应该打开。

您希望在屏幕上显示一个非常大的整数。不幸的是,屏幕出BUG了:不能同时打开超过n个片段。所以现在你想知道什么是最大的整数可以显示通过打开不超过n段。

你的程序应该能够处理t个不同的测试用例。

题解:贪心问题,能够尽量得到最大的数那就让数位最大。类似于之前的拿物品问题,可以看出1的占有是最小的,所以在取数的时候优先取1,但是如果n是奇数的话会有剩余,又可以发现7的占有是3所以n是奇数的时候就是将最高位的1换成7就可。

AC代码(我的):

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int main()
{
	int t;
	cin >> t;
	while(t--){
		int n,sum;
		cin >> n;
		sum = n/2;
		if(n % 2 == 0){
			for(int i = 0;i < sum;i++){
				cout << '1';
			}
			cout << endl;
		}
		else{
			cout << '7';
			for(int i = 1;i < sum;i++){
				cout << '1';
			}
			cout << endl;
		}
	}
	return 0;
}

C.Food Buying(CF1000)

题目描述+题解:类似于商场返利,购买x价值的物品就会返利x/10;相当于每次扣费0.9x。这个的话也是贪心的思维,每次让他的返利最大,就可以直接按数位递减下来。注意要每次进行数据更新。

AC代码(师姐的~):

#include<bits/stdc++.h>
#pragma warning(disable:4996)
typedef long long ll;
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int sum=0;
		int x;
		cin >> x;
		while (x>=10) 
		{
			int y = x % 10;
			sum += x - y;
			x = (x - y) / 10 + y;
		}
		sum += x;
		cout << sum << endl;

	}
	return 0;
}

PS:这个题我还在每次更新位数,,,,TAT

D.ConneR and the A.R.C. Markland-N CF(1100)

题目描述:zls住在一个n层的私人大别墅里(zlsnb!)现在zls在s层,他现在想去吃饭,但是每天都会有k层楼是关闭的,zls不能在这些楼上吃东西。现在zls希望走最少的路就可以到达吃饭的地方,问zls最少走几层。

题解:二分题目,我一开始想二分它的步数范围,也就是0—max(s,n-s),但是直接在第二个样例上T了。
其实这个题目可以这样想:我们通过k的取值可以看出,这栋楼最多封闭1000层,那么我们假设(s-1000,s + 1000)的楼层全部封闭了然后二分法找到离s最近的楼层。注意二分的时候一定要把封闭的楼层给排下序。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2005;
ll a[maxn] = {};		
ll n,s,k;
int check(int x)
{
	ll low = 0;
	ll high = k;
	while(low <= high){
		ll mid = (high + low) >> 1;
		if(a[mid] == x) return 0;
		else if(a[mid] > x){
			high = mid - 1;
		}
		else if(a[mid] < x){
			low = mid + 1;
		}
	}
	return 1;
}
int main()
{
	int t;
	cin >> t;
	while(t--){
		cin >> n >> s >> k;
		for(int i = 1;i <= k;i++){
			cin >> a[i];
		}
		sort(a + 1,a + 1 + k);
		ll ans = 0x3f3f3f3f;
		for(int i = max((ll)1,s - 1000);i <= min(s + 1000,n);i++){
			if(check(i)){
				ans = min(ans,abs(i - s));
			}
		}
		cout << ans << endl;
	}
	return 0;
}

E.Product of Three Numbers(CF1300)

题目描述:给出一个正整数,问能否将其拆成三个不同数之积。

题解:这样想,每次对该正整数取根号以后查找因子,只要找到就记录因子后更新正整数的值,然后直到找到两个因子,最后剩下的部分就是第三个因子了。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 5;
ll a[maxn];
int main()
{
	int t;
	cin >> t;
	while(t--){
		ll n,temp = 2,num = 0,ans = 0;
		cin >> n;
		for(int i = temp;i <= (int)sqrt(n);i++){
			if(ans == 2) break;
			if(n % i == 0){
				a[num++] = i;//记录因子
				n = n/i; //每次更新n的值
				temp = i + 1;//防止前两个因子重复
				ans++;
			}
		}
		if(ans == 2&&a[0] != a[1]&&a[0] != n&&a[1] != n){
			cout << "YES" << endl;
			cout << a[0] << ' ' << a[1] << ' ' << n << endl;
		}
		else cout << "NO" << endl;
	}
	return 0;
}

F.Shortest path of the king(CF1200)

题目描述:给出了一个棋盘,问国王从当前位置走到目标位置的最短路。

题解:三角形边长关系可以得知:优先走对角线即可。对与等腰直角三角形,可以直接走对角线,但是对于一般直角三角形呢?也是优先走对角线。可以得出,总的走的次数是最长边的长度,每次走对角线的次数就是三角形的短边长度,然后根据两点位置关系确定方向。

AC代码:(强行模拟QAQ)

#include<bits/stdc++.h>
using namespace std;
int a[10][10];
int main()
{
	char x1,x2;
	int y1,y2,sum;
	cin >> x1 >> y1;
	cin >> x2 >> y2;
	if(abs(x1 - x2) == abs(y1 - y2)){
		sum = abs(y1 - y2);
		cout << sum << endl;
		if(x1 > x2&&y1 > y2){
			for(int i = 0;i < sum;i++){
				cout << "LD" << endl;
			}
		}
		else if(x1 > x2&&y1 < y2){
			for(int i = 0;i < sum;i++){
				cout << "RD" << endl;
			}
		}
		else if(x1 < x2&&y1 < y2){
			for(int i = 0;i < sum;i++){
				cout << "RU" << endl;
			}
		}
		else if(x1 < x2&&y1 > y2){
			for(int i = 0;i < sum;i++){
				cout << "RD" << endl;
			}
		}
	}
	else{
		int temp1 = min(abs(x1 - x2),abs(y1 - y2));
		int temp2 = max(abs(x1 - x2),abs(y1 - y2));
		sum = temp2;
		cout << sum << endl;
		if(x1 >= x2&&y1 >= y2){
			for(int i = 0;i < temp1;i++){
				cout << "LD" << endl;
			}
			for(int i = 0;i < temp2 - temp1;i++){
				printf("%s\n",abs(x1 - x2) > abs(y1 - y2)?"L":"D");
			}
		}
		else if(x1 <= x2&&y1 >= y2){
			for(int i = 0;i < temp1;i++){
				cout << "RD" << endl;
			}
			for(int i = 0;i < temp2 - temp1;i++){
				printf("%s\n",abs(x1 - x2) > abs(y1 - y2)?"R":"D");
			}
		}
		else if(x1 <= x2&&y1 <= y2){
			for(int i = 0;i < temp1;i++){
				cout << "RU" << endl;
			}
			for(int i = 0;i < temp2 - temp1;i++){
				printf("%s\n",abs(x1 - x2) > abs(y1 - y2)?"R":"U");
			}
		}
		else if(x1 >= x2&&y1 <= y2){
			for(int i = 0;i < temp1;i++){
				cout << "LU" << endl;
			}
			for(int i = 0;i < temp2 - temp1;i++){
				printf("%s\n",abs(x1 - x2) > abs(y1 - y2)?"L":"U");
			}
		}
	}
	return 0;
}

G - Chat Server’s Outgoing Traffic(CF1200)

题目描述:Polycarp 正在致力于一个名为 “Polychat” 的新项目。他决定,这个项目也应当包含聊天功能,以紧随 IT 领域的现代趋势。为了达到这个目标,Polycarp 已经在自己的笔记本电脑前花了数小时,实现了一个聊天服务器,它能够处理三种类型的命令:

  • 将联系人加入到聊天中 (‘Add’ 命令)。
  • 将联系人从聊天中移除 (‘Remove’ 命令)。
  • 从某个联系人发送消息给聊天中的所有人,包含发送消息者本人 (‘Send’ 命令)。

现在,Polycarp 想要知道当处理一个特定的命令集时,服务器将要产生的数据流出量。

Polycarp 知道,聊天服务器不会为 ‘Add’ 和 ‘Remove’ 命令而产生流出数据量。 当处理 ‘Send’ 命令时,服务器向聊天的每个参与者发送 l 比特的数据量,其中 l 是消息的长度。

由于 Polycarp 没有时间,他请求您帮助他解决这个问题。

题解:其实就是个模拟…但是我一直不知道输出在哪里输出…

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s;
	int cnt = 0,sum = 0,temp; 
	while(getline(cin,s)){
		if(s[0] == '+') cnt++;
		else if(s[0] == '-') cnt--;
		else{
			int len = s.length();
			for(int i = 0;i < len;i++){
				if(s[i] == ':') {
					temp = i;
					break;
				}
			}
			sum += (len - temp - 1) * cnt;
		}
	}
	cout << sum << endl; //其实放这里就可以了......
	return 0;
 } 

H.Triangle(CF1300)

题目描述:其实这是一道打着1300旗号的水题…

给你4根不同长度的木棒,不能折断,现在问能否用其中的三根组成三角形。

1.如果满足三角形三边条件则输出TRIANGLE。

2.如果三边关系满足两边之和等于第三边则输出SEGMENT。

3.如果都不满足输出IMPOSSIBLE。
题解:介于数据不大,可以对三边的长度排序,然后分别取1,2,3和2,3,4检验即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int a[5];
bool cmd(int x,int y)
{
	return x < y;
}
int main()
{
	for(int i = 0;i < 4;i++){
		cin >> a[i];
	}
	sort(a,a + 4,cmd);
	if(a[0] + a[1] > a[2]||a[1] + a[2] > a[3]) cout << "TRIANGLE" << endl;
	else if((a[0] + a[1] == a[2]&&a[1] + a[2] < a[3])||(a[0] + a[1] < a[2]&&a[1] + a[2] == a[3])||(a[1] + a[0] == a[2]&&a[1] + a[2] == a[3])) cout << "SEGMENT" << endl;
	else if(a[0] + a[1] < a[2]&&a[1] + a[2] < a[3]) cout << "IMPOSSIBLE" << endl;
	return 0;
}

I.Kalevitch and Chess(CF1300)

题目描述:同样一道水题…

一位著名的 Berland 画家 Kalevitch 喜欢让公众大吃一惊。他最近一次令人称奇的创新,是国际象棋。过去一千余年以来,人们一直在枯燥无趣的棋盘上,玩这个古老的游戏。Kalevitch 决定终结这个传统,将新的风格引入到棋盘中来。

与过去一样,棋盘是由方格图案组成,方格位于 8 × 8 的网格之中,每个方格被涂色为黑或白。Kalevitch 建议,棋盘应当按以下方式涂色:应当选中一条 8 个方格的水平线或竖直线 (即一行或一列),然后涂为黑色。最初,整个棋盘是白色的,可以按以上描述的方式涂色一次或多次。允许对一个方格涂色多次,但首次涂色之后,它的颜色不再改变并保持为黑色。Kalevitch 整洁地为棋盘涂色,对于某个方格而言,无法判断它是在竖直还是水平的方向被涂色。

Kalevitch 希望这样的棋盘得到普及,并且他将被委托为棋盘涂色,这将帮助他度过舒适的晚年生活。客户们将通知他,他们想要什么样的棋盘,而画家将会对白色的棋盘涂色,以满足客户们的需求。

不用说,这样的业务应当节省一切 — 对于每次委托,他想知道最少的绘制次数,以满足客户的要求。请帮助 Kalevitch 完成这项任务。

题解:正常模拟就行,特判一下全是B的情况,然后每次只需要考察第一列和第一行。

AC代码:

#include<bits/stdc++.h>
using namespace std;
char a[10][10];
int main()
{
	int temp = 0;
	for(int i = 0;i < 8;i++){
		for(int j = 0;j < 8;j++){
			cin >> a[i][j];
			if(a[i][j] == 'B') temp++;
		}
	}
	if(temp == 64){
		cout << '8' << endl;
		return 0;
	}
	int sum = 0;
	for(int i = 0;i < 8;i++){
		int ans1 = 1;
		if(a[i][0] == 'B'){
			for(int j = 1;j < 8;j++){
				if(a[i][j] == 'B')ans1++;
			}
			if(ans1 == 8) sum++;
		}
	}
	for(int i = 0;i < 8;i++){
		int ans2 = 1;
		if(a[0][i] == 'B'){
			for(int j = 1;j < 8;j++){
				if(a[j][i] == 'B') ans2++;
			}
			if(ans2 == 8) sum++;
		}
	}
	cout << sum << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CUCKyrie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值