这套CF练习题感觉有点迷,坑好多
A - Chord
思路:
- 给予C 、C#、D、D#、E、F、F#、G、G#、A、B、H,这12个符号,题目给予3个符号,如果相隔 4 3,那么就输出“major”,如果相隔3 4,就输出“minor”,否则就输出“strange”。
- 排着循环遍历即可,判断他们之间的距离(mp存一下),然后判断输出即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <stack>
#include <cmath>
#include <deque>
using namespace std;
typedef long long ll;
const int N = 100010, M = 200010;
const int mod = 1e9 + 7;
struct node
{
string st;
int n;
}ans[N];
bool cmp(node x, node y){
if (x.st[0] == y.st[0]) return x.n < y.n;
return x.st[0] < y.st[0];
}
// string s[12] = {"C","C#","D","D#","E","F","F#","G","G#","A","B","H"};
unordered_map<string ,int> mp;
int main(){
string a, b, c;
cin>>a>>b>>c;
mp["C"] = 1;
mp["C#"] = 2;
mp["D"] = 3;
mp["D#"] = 4;
mp["E"] = 5;
mp["F"] = 6;
mp["F#"] = 7;
mp["G"] = 8;
mp["G#"] = 9;
mp["A"] = 10;
mp["B"] = 11;
mp["H"] = 12;
ans[0].st = a;
ans[0].n = a.length();
ans[1].st = b;
ans[1].n = b.length();
ans[2].st = c;
ans[2].n = c.length();
sort(ans, ans + 3, cmp);
int f = 0;
for (int i = 0; i < 3; i ++){
int x = mp[ans[i%3].st];
int y = mp[ans[(i + 1)%3].st];
int z = mp[ans[(i + 2)%3].st];
int xy = (12 + y - x ) % 12;
int yz = (12 + z - y ) % 12;
if (xy == 4 && yz == 3) {
puts("major");
f = 1;
return 0;
}
if (xy == 3 && yz == 4){
puts("minor");
f = 1;
return 0;
}
}
if (!f) puts("strange");
return 0;
}
B - Keyboard
思路:
- 这题比较坑,首先说一下坑点,就是S算Shift(就是必须S + s 才能敲出来S),还有就是字符不一定就出现一次(我一开始以为就1个)
- 大体思路就是先存储一遍S的位置,然后我们再遍历求小写字母能敲出大写字母时距离最近的S的距离,然后遍历即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <stack>
#include <cmath>
#include <deque>
#include <set>
using namespace std;
typedef long long ll;
const int N = 100010, M = 200010;
const int mod = 1e9 + 7;
char a[1010][1010];
ll g[N];
struct node
{
int x, y;
}mp[N],bb[N];
int main(){
int cnt = 0;
set<char> res;
int n, m, x;
scanf("%d%d%d",&n,&m,&x);
int xx = 0;
for (int i = 1; i <= n; i++){
string st;
cin>>st;
for (int j = 0; j < m; j ++){
a[i][j + 1] = st[j];
if (a[i][j + 1] == 'S'){
xx = i;
bb[cnt].x = i;
bb[cnt ++].y = j + 1;
}
// mp[(int)a[i][j + 1]].x = i;
// mp[(int)a[i][j + 1]].y = j + 1;
res.insert(a[i][j + 1]);
}
}
for (int i = 0; i < 10000; i ++){
g[i] = 1000000000000;
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
char s = a[i][j];
if (s == 'S') continue;
g[(int)s] = 0;
if (s >= 'a' && s <= 'z' && xx != 0){
for (int k = 0; k < cnt; k ++){
ll dist = ((i - bb[k].x) * (i - bb[k].x) + (j - bb[k].y) * (j - bb[k].y));
g[int(s) - 32] = min(g[int(s) - 32],dist);
}
}
}
}
int q;
scanf("%d",&q);
int num = 0;
string st;
cin>>st;
for (int i = 0; i < q; i++){
char s = st[i];
// printf("%f\n",g[(int)s]);
if (g[(int)s] == 1000000000000) {
puts("-1");
return 0;
}
else{
if (g[(int)s] > x * x) num ++;
}
}
printf("%d\n",num);
return 0;
}
C - Trains
思路:
- 稍微有点绕,最终求去哪个女友那里次数多
- 首先我们先求出他们的最小公倍数,这样我们按照一个周期来计算,直接暴力即可,我们一个一个判断该时间段,应该去哪个女友那里,看例子应该能看明白,比如 2 3, 那么1 2 时刻肯定是等车去女友D那里,3时刻去女友M,4时刻去女友D,这里最终的关键是最后,5 6 时刻,他们都相同,相同时刻都可以去女友那里,然后去去的少的女友那里,所以5 6 去女友M那里,所以他们的时间相同,所以是Equal。
- 所以我们只要慢慢取最小值即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <stack>
#include <cmath>
#include <deque>
using namespace std;
typedef long long ll;
const int N = 100010, M = 200010;
const int mod = 1e9 + 7;
long long gcd(long long a,long long b){
if (a > b){
long long temp = a;
a = b;
b = temp;
}
while(b%a!=0){
long long temp = b%a;
b = a;
a = temp;
}
return a;
}
int main(){
ll a, b;
scanf("%lld%lld",&a,&b);
ll g = a * b / gcd(a,b);
ll n1 = 1, n2 = 1;
ll mi = 0;
ll ra = 0, rb = 0;
while(1){
ll x = n1 * a;
ll y = n2 * b;
ll t = min(x, y);
if (t == x) n1 ++;
else n2 ++;
if (t == g){
if (ra > rb) rb += g - mi;
else ra += g - mi;
break;
}
if (t % a == 0) ra += t - mi;
if (t % b == 0) rb += t - mi;
mi = t;
}
if (ra == rb) puts("Equal");
else if (ra > rb) puts("Dasha");
else puts("Masha");
return 0;
}
D - Vasya and Types
思路:
- 首先存储一下初始void(用mp存一下),然后每次操作:
- 如果是def ,那么我们计算& 和 * 的数目,然后计算原本的字符,然后如果num <= 0 ,那么直接err, 而且err后无论有多少 * ,都是err(很坑),然后我们排着模拟计算即可,然后最后计算数值进行保存。
- 如果是of ,那么直接输出即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <stack>
#include <cmath>
#include <deque>
using namespace std;
typedef long long ll;
const int N = 100010, M = 200010;
const int mod = 1e9 + 7;
string a, b, c;
int num = 0;
unordered_map<string,int> mp;
void solve(){
cin>>b;
int n = b.length();
string d = "";
num = 0;
int cnt = 0;
for (int i = 0; i < n; i++){
if (b[i] == '&'){
cnt --;
}
else if (b[i] == '*'){
cnt ++;
}
else{
d += b[i];
}
}
num = mp[d];
if (mp[d] > 0) num += cnt;
else num = 0;
}
int main(){
int n;
scanf("%d",&n);
mp["void"] = 1;
for (int i = 1; i <= n; i++){
cin>>a;
if (a == "typedef"){
solve();
cin>>c;
mp[c] = num;
}
else{
solve();
if (num <= 0) puts("errtype");
else{
printf("void");
for (int i = 0; i < num - 1; i ++){
printf("*");
}
puts("");
}
}
}
return 0;
}