咕咕东的奇遇
咕咕东是个贪玩的孩子,有一天,他从上古遗迹中得到了一个神奇的圆环。这个圆环由字母表组成首尾相接的环,环上有一个指针,最初指向字母a。咕咕东每次可以顺时针或者逆时针旋转一格。例如,a顺时针旋转到z,逆时针旋转到b。咕咕东手里有一个字符串,但是他太笨了,所以他来请求你的帮助,问最少需要转多少次。
Input
输入只有一行,是一个字符串。
Output
输出最少要转的次数。
Sample input
zeus
Sample output
18
解题思路
签到题,对于每次找字幕判断顺时针转比较近还是逆时针转比较近,累加即可
#include<iostream>
#include<cmath>
#include<algorithm>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
#define ll long long
string s;
ll ans = 0;
int cal(char x,char y)
{
int numx = x - 'a';
int numy = y - 'a';
if(numx > numy)
{
int t = numx;
numx = numy;
numy = t;
}
if((numy-numx) >= 0 && (numy-numx) < (numx+26-numy))
{
return (numy-numx);
}
else return (numx+26-numy);
}
int main()
{
cin>>s;
char c = 'a';
for(int i=0;i<s.length();i++)
{
ans += cal(c,s[i]);
c = s[i];
}
cout<<ans;
return 0;
}
咕咕东想吃饭
咕咕东考试周开始了,考试周一共有n天。他不想考试周这么累,于是打算每天都吃顿好的。他决定每天都吃生煎,咕咕东每天需要买ai个生煎。但是生煎店为了刺激消费,只有两种购买方式:①在某一天一次性买两个生煎。②今天买一个生煎,同时为明天买一个生煎,店家会给一个券,第二天用券来拿。没有其余的购买方式,这两种购买方式可以用无数次,但是咕咕东是个节俭的好孩子,他训练结束就走了,不允许训练结束时手里有券。咕咕东非常有钱,你不需要担心咕咕东没钱,但是咕咕东太笨了,他想问你他能否在考试周每天都能恰好买ai个生煎
Input
输入两行,第一行输入一个正整数n(1<=n<=100000),表示考试周的天数。
第二行有n个数,第i个数ai(0<=ai<=10000)表示第i天咕咕东要买的生煎的数量。
Output
如果可以满足咕咕东奇怪的要求,输出"YES",如果不能满足,输出“NO”。(输出不带引号)
Sample input1
4
1 2 1 2
Sample output1
YES
Sample input2
3
1 0 1
Sample output2
NO
解题思路
当时在做这道题的时候思路跑偏了,看了n的范围以为一定得遍历一下一天一天地记录答案,后来发现这样反而很麻烦,n * ai的枚举显然无法接受,后来想到分ai为奇数偶数的情况考虑就可以了,但是由于在错误的思路上跑了太久最后也没改回来,这题没AC实在是不应该。
解法是一个并不复杂的贪心,今天要买偶数个就买,要买奇数个且手里没券就让券个数加一,否则用一个券。到了要买0个的某一天或者到了最后手里还有废券则是不合法的
#include<iostream>
#include<cmath>
#include<algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
using namespace std;
#define ll long long
int n,x,tickets;
bool flag;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
if(x%2)
{
if(tickets == 0)
{
tickets++;
}
else
{
tickets--;
}
}
else
{
if(x==0)
{
if(tickets)
{
flag = true;
break;
}
}
}
}
if(tickets%2||flag)
{
cout<<"NO";
}
else
{
cout<<"YES";
}
return 0;
}
可怕的宇宙射线
宇宙射线深入人心
众所周知,瑞神已经达到了CS本科生的天花板,但殊不知天外有天,人外有苟。在浩瀚的宇宙中,存在着一种叫做苟狗的生物,这种生物天生就能达到人类研究生的知识水平,并且天生擅长CSP,甚至有全国第一的水平!但最可怕的是,它可以发出宇宙射线!宇宙射线可以摧毁人的智商,进行降智打击!
宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的左右45°方向分裂出两条宇宙射线,同时威力不变!宇宙射线会分裂n次,每次分裂后会在分裂方向前进ai个单位长度。
现在瑞神要带着他的小弟们挑战苟狗,但是瑞神不想让自己的智商降到普通本科生zjm那么菜的水平,所以瑞神来请求你帮他计算出共有多少个位置会被"降智打击"
Input
输入第一行包含一个正整数n,(n<=30),表示宇宙射线会分裂n次。
第二行包含n个正整数a1,a2,⋯,an,第i个数ai(ai≤5)表示第i次分裂的宇宙射线会在它原方向上继续走多少个单位长度。
Output
输出一个数ans,表示有多少个位置会被降智打击。
Sample input
4
4 2 2 3
Sample output
39
解题思路
比赛时看出来要出正解就要结合数学推导,但是这个过程没有看明白,自己随便蒙了个式子上去也没得分。赛后逛了很久别人的博客,学到了解决办法。
这个图是一个不断往外对称的过程,由于越往后分裂,图的分叉越多,所以我们从最后一次对称回溯往前算,将所有的点加入set,因为set内部元素有序且自动去重,记录答案很方便,最后输出size就是答案。
#include<iostream>
#include<cmath>
#include<algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <set>
using namespace std;
#define ll long long
struct node
{
int x,y;
bool operator < (const node& b)const
{
return x != b.x ? x < b.x : y < b.y;
}
};
set<node>mmap;
int v[51],n;
int qx[] = {0,1,1,1,0,-1,-1,-1};
int qy[] = {1,1,0,-1,-1,-1,0,1};
void dfs(node p,int cnt,int direct)
{
if(cnt > n)return;
dfs({p.x + qx[direct] * v[cnt], p.y + qy[direct] * v[cnt]},cnt + 1,(direct + 1)%8);//往后分裂
set<node>temp;//记录本次分裂往前延申到的点
for(auto& i : mmap)
{
if(direct == 0 || direct == 4)
{
temp.insert({p.x * 2 - i.x,i.y});
}
else if(direct == 2 || direct == 6)
{
temp.insert({i.x,p.y * 2 - i.y});
}
else if(direct == 1 || direct == 5)
{
temp.insert({i.y + p.x - p.y,i.x + p.y - p.x});
}
else if(direct == 3 || direct == 7)
{
temp.insert({p.x + p.y - i.y,p.x + p.y - i.x});
}
}
mmap.insert(temp.begin(),temp.end());
for(int i = 1; i<= v[cnt]; i++)
{
mmap.insert({p.x + qx[direct] * i,p.y + qy[direct] * i});
}
}
int main()
{
cin>>n;
for(int i = 1;i <= n;i++)
{
cin>>v[i];
}
dfs({0,0},1,0);
cout<<mmap.size();
return 0;
}