比赛链接
A. Even Odds
题意:
给你一个长整型的 n,将1-n之间的奇数进行升序排列,然后对偶数进行升序排列,问排列中第k个数是多少.
思路:
找规律:
如果 k <= 奇数的个数,那么答案就是 2*k -1 ,因为对于 1 3 5 7 9.....这个数列的通项公式为2 * k - 1.
否则
答案就是(k - count_odd) * 2;
但是要注意开long long.
参考代码:
void solve() {
ll n, k;
std::cin >> n >> k;
ll c_odd = std::ceil(n / 2.0);
if (k <= c_odd)
std::cout << (k << 1) - 1;
else
std::cout << ((k - c_odd) << 1);
}
B. Strings of Power
题意:
给你一个字符串,问有多少个子串是以"heavy"开头并且以"metal"结尾?
思路:
记录"heavy"出现的次数,遇到"metal”,那么方案数就是前面"heavy"出现的次数,注意开long long,并且特判字符串长度小于10的情况.
参考代码:
void solve() {
ll ans{}, pre{};
std::string s;
std::cin >> s;
if (s.size() < 10) {
std::cout << "0\n";
return;
//特判 !
}
for (unsigned int i = 0; i < s.size() - 4; i++) {
std::string sub = s.substr(i, 5);
pre += (sub == "heavy");
if (sub == "metal")
ans += pre;
}
std::cout << ans << '\n';
}
C. Perfect Pair
题目大意:
给你三个整数 x y m ,可以进行无数次操作, 每次操作可以用 x+y 来替换 x 或者 替换 y,问最少几次操作之后可以使得max(x,y)>=m ,如果无法实现,那么输出 -1;
思路:
第一种情况:
max(x,y) >= m,输出0
第二种情况:
max(x,y) <m ,并且 max (x,y) <=0 ,那么x+y<=0,无法实现.
第三种情况:
max(x,y) <m,并且max(x,y) >0.
如果min(x,y)<0,那么先把他加成正数.
虽然在目前来说 x+y 大数加小数与小数加大数没区别,可我们要选择小数加大数,这样可以使两个数整体的和加大。
举个例子:
一对数(x,y) , x=1,y=5 。
当选择大数加小数时:
第一轮:
x=1,y=6 ,x 与 y 的最大值为 6 。
第二轮:
x=1,y=7 , x 与 y 的最大值为 7 。
当选择小数加大数时:
第一轮:
x=6,y=5 ,x与 y 的最大值为 6 。
第二轮:
x=6,y=11,x与 y 的最大值为 11 。
通过例子不难看出小数加大数的值是较大的,所以我们要选择小数加大数。
参考代码:
void solve()
{
ll x, y, m, ans{};
std::cin >> x >> y >> m;
if (std::max(x, y) >= m) {
// 第一种情况
std::cout << 0;
return;
}
if (x <= 0 && y <= 0) {
// 第二种情况
std::cout << -1;
return;
}
if (x * y < 0) {
// 如果这两个数一正一负
if (x < y) {
ans += (-x) / y; // 这个数要加几次
x = x % y; // 等价于 x+=y*((-x)/y)
} else {
ans += (-y) / x;
y = y % x;
}
}
while (std::max(x, y) < m) {
if (x > y) {
y += x;
} else {
x += y;
}
ans++;
}
std::cout << ans;
}