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;
}