具体详情:比赛链接🔗
一共有ABCDEFG1G2七个题目,这一次先总结一下A
A.A+B Again?
这个题就是给出t个两位或一位数字,求出每个数字的各位数之和。
因为它限制了数字的最大限制就是两位数。所以这个题比较好解。
我当时提交的代码如下。
#include <iostream>
#include <string>
using namespace std;
int main()
{
int t;
int arr[100];
cin >> t;
for (int i = 1; i <= t; i++)
{
cin >> arr[i];
}
for (int i = 1; i <= t; i++)
{
int sum = 0;
sum = arr[i] % 10 + arr[i] / 10;
cout << sum << endl;
}
return 0;
}
但是,现在看,进行数字的存储是没有必要的!
B. Card Game
这个题大概的意思就是两个玩家各自会拿到两张牌,这两张牌原始都是向下的,即背面向上,两个人都不知道原始的牌。然后分为两个轮回分别掀开各自的两张牌。
输出结果是 Suneet会赢的话,会有几种方式赢。
根据题意,只有 Suneet的牌严格大于Slavic的牌时,Suneet才会赢得第一回合。只有Suneet赢得回合数严格大于Slavic的回合数时,Suneet才会赢。
(两个人牌数相等时,平局。回合数相等时,谁也不赢。)
主要这道题因为每个人只有四张牌,即是对于Suneet而言,先出一张,留下一张。列出来所有的可能即可。
#include <iostream>
#include <string>
using namespace std;
int arr[100000][5];
int main()
{
int t;
int a1, a2, b1, b2;
cin >> t;
for (int i = 1; i <= t; i++)
{
cin >> arr[i][1] >> arr[i][2] >> arr[i][3] >> arr[i][4];
}
for (int i = 1; i <= t; i++)
{
int sum = 0;
a1 = arr[i][1]; a2 = arr[i][2]; b1 = arr[i][3]; b2 = arr[i][4];
//a1--b1
if ((a1 > b1 && a2>b2 ) ||( a1 == b1 && a2 > b2) || (a1 > b1 && a2 == b2) )sum++;
//a2--b1
if ((a2 > b1 && a1 > b2) || (a2 == b1 && a1 > b2) || (a2 > b1 && a1 == b2)) sum++;
//a2--b1
if ((a2 > b1 && a1 > b2)||(a2 == b1 && a1 > b2) || (a2 > b1 && a1 == b2)) sum++;
//a2--b2
if ((a2 > b2 && a1 > b1) || (a2 == b2 && a1 > b1) || (a2 > b2 && a1 == b1)) sum++;
cout << sum<<endl;
}
return 0;
}
C. Showering
以上图为例,这道题意思大概就是这个人一共有10分钟(输入),然后有3段时间忙碌(输入),每段时间忙碌几分钟(输入),洗澡需要几分钟(输入),那么这个人这一天能否洗澡。输出YES or NO。
#include <iostream>
using namespace std;
int main()
{
int t;
cin >> t;
for (int i=0;i<t;i++)
{
int n, s, m;
cin >> n >> s >> m;
string str = "NO";
int temp = 0;
for (int i=0;i<n;i++)
{
int a, b=0;
cin >> a>>b;
if (a - temp >= s) { str = "YES"; }
temp = b;
}
if (m - temp >= s)str = "YES";
cout << str << endl;
}
return 0;
}
D. Slavic’s Exam
这个题大概意思就是改变s中的?,使得t能成为s的子串。如果可以,则输出YES,并随意输出任意的一个改变后的s;如果不满足,则输出NO。
首先t成为s的字串一定是t的长度小于等于s的长度的。
然后这个题的核心问题就是怎么样判断字串问题。
我的大概思路就是如下图。(雄安不考虑题目中的?问题)
循环较长的字符串,刚开始对于较短的字符串设置一个指针,如果在较长的字符串中循环到的字符与较短的字符串的当前字符相同,则指针移动。
很明显,如果对于较长的字符串,循环一遍过后,较短的字符串的指针能够出现在其最后的一个字符的后面,即说明是子串。
对于这个题目,特殊处理一下“?”即可。
#include <iostream>
#include <string>
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
string s,t;
cin >> s >> t;
string ans="NO";
if (t.length() <= s.length())
{
int j = 0;
for (int i = 0; i < s.length() && j<t.length(); i++)
{
if (t[j] == s[i])j++;
else if (s[i] == '?') {
s[i] = t[j];
j++;
}
}
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '?') s[i] = 'a';
}
if (j == t.length()) ans = "YES";
}
cout << ans<<endl;
if (ans == "YES")cout << s << endl;
}
return 0;
}
E. Triple Operations
对于这个问题,首先就是动态规划思想,计算出每个数变为0需要多少次。
其次就是前缀和,计算1~x个数即前x个数变为0一共需要多少次。
然后,对于每个测试用例,直接累加 [l,r] 范围内的数的操作次数即可。
(然后我现在也还是不太理解题目中说的 一个变大3x,这个有什么关系呢。困惑啊)
#include <iostream>
using namespace std;
const int N = 10000;
const int R = 200000;
int main()
{
int t;
cin >> t;
int f[R + 1];
f[0] = 0;
for (int i = 1; i <= R; i++)
{
f[i] = f[i / 3] + 1;
}
for (int i = 1; i <= R; i++)
{
f[i] += f[i - 1];
}
while (t--)
{
int l, r;
cin >> l >> r;
cout << f[l] + f[r] - 2 * f[l - 1]<<endl;
}
return 0;
}