Google kickstart 2022 Round A题解
Speed Typing
题意概述
给出两个字符串I
和P
,问能否通过删除P
中若干个字符得到I
?如果能的话,需要删除字符的个数是多少?
数据规模
\]
双指针
设置两个指针i
和j
分别指向I
和P
的第一个字符,滑动指针j
,如果j
指向的字符与i
指向的字符相同,则让i
向后滑动一个字符,当i
滑动到I
字符串末尾或j
滑动到P
字符串末尾后即可结束循环。如果i
滑动到I
字符串末尾,则说明可以通过删除P
中若干个字符得到I
,那么删除的字符个数为\(|P|-|I|\);反之则不能。
复杂度
- 时间复杂度为\(O(max(|I|,|P|))\)。
- 空间复杂度为\(O(1)\)。
C++代码
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
#define rep(i, a, b, c) for (gg i = (a); i <= (b); i += (c))
#define rrep(i, a, b, c) for (gg i = (a); i >= (b); i -= (c))
constexpr gg MAX = 1e6 + 5;
constexpr gg mod = 1e9 + 7;
constexpr gg INF = 4e18;
constexpr double eps = 1e-12;
gg ti, ni, mi, ki, di, pi, xi, yi;
gg up(gg n, gg m) { return n >= 0 ? (n + m - 1) / m : n / m; }
gg down(gg n, gg m) { return n >= 0 ? n / m : (n - m + 1) / m; }
//! ti; MAX; mod; 边界
void solve() {
string s1, s2;
cin >> s1 >> s2;
gg i = 0, j = 0;
for (; i < s1.size() and j < s2.size(); ++i, ++j) {
while (j < s2.size() and s1[i] != s2[j]) {
++j;
}
if (j == s2.size()) {
break;
}
}
i == s1.size() ? cout << s2.size() - s1.size() : cout << "IMPOSSIBLE";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ti = 1;
cin >> ti;
for (gg ii = 1; ii <= ti; ++ii) {
cout << "Case #" << ii << ": ";
solve();
cout << "\n";
}
return 0;
}
Challenge Nine
题意概述
给定一个正整数\(N\),在给定的数字\(N\)的任意位置插入一个[0,9]
之间的数字,得到一个不带前导零的新的数字,需要保证这个新的数字是9的倍数。问能构造出的最小的数字是多少?
数据规模
\]
贪心
由于给出的数字非常大,需要用字符串读入。易知一个数字是9的倍数的充要条件是该数各位上的数字之和也是9的倍数。因此,先计算出读取的字符串各位上的数字之和sum
,遍历0~9
这10个数字,假设当前遍历到的数字是i
,如果i
与sum
之和是9的倍数,说明插入i
能够保证新数字是9的倍数。接着从N
的高位向低位遍历,假设当前遍历到的位上的数字是j
,如果i<j
,则将i
插入到j
之前可以得到最小的数字(想一想为什么?)。
复杂度
- 时间复杂度为\(O(n)\)。
- 空间复杂度为\(O(n)\)。
其中\(n\)指的是数字N
的位数。
C++代码
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
#define rep(i, a, b, c) for (gg i = (a); i <= (b); i += (c))
#define rrep(i, a, b, c) for (gg i = (a); i >= (b); i -= (c))
constexpr gg MAX = 1e6 + 5;
constexpr gg mod = 1e9 + 7;
constexpr gg INF = 4e18;
constexpr double eps = 1e-12;
gg ti, ni, mi, ki, di, pi, xi, yi;
gg up(gg n, gg m) { return n >= 0 ? (n + m - 1) / m : n / m; }
gg down(gg n, gg m) { return n >= 0 ? n / m : (n - m + 1) / m; }
//! ti; MAX; mod; 边界
void solve() {
string n;
cin >> n;
gg m = n.size(), sum = 0;
array<gg, 2> ans{m + 1, 10};
for (char c : n) {
sum += c - '0';
}
n.push_back(10 + '0');
rep(i, 0, 9, 1) {
if ((i + sum) % 9 == 0) {
rep(j, 0, m, 1) {
if (n[j] - '0' > i and (j > 0 or i != 0) and ans[0] > j) {
ans = {j, i};
break;
}
}
}
}
n.pop_back();
cout << n.substr(0, ans[0]) << ans[1] << n.substr(ans[0]);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ti = 1;
cin >> ti;
for (gg ii = 1; ii <= ti; ++ii) {
cout << "Case #" << ii << ": ";
solve();
cout << "\n";
}
return 0;
}
Palindrome Free Strings
题意概述
给出一个长度为\(N\)的只包含0
、1
和?
构成的字符串S
,可以随机用0
、1
替换掉字符串S
中所有的?
,问能否找到一种替换方法,使得所得到的串没有长度大于等于5的回文子串。
数据规模
\]
动态规划
首先需要注意到,如果字符串S
中包含长度为\(n(n>2)\)的回文子串,那么将该回文子串首尾两个字符,那么得到的长度为\(n-2\)的子串必然也是回文的,因此,可以得到结论:如果S
中不包含长度为5的回文子串,那么S
中必然也不包含长度为\(5+2k(k>0)\)的回文子串;如果S
中不包含长度为6的回文子串,那么S
中必然也不包含长度为\(6+2k(k>0)\)的回文子串。因此,只要能够找到一种替换方法使得S
不包含长度为5和6的回文子串,那么S
中必然也没有长度大于等于5的回文子串。
一种暴力的方法,是通过递归的方法将S
中的字符?
逐个替换为0
或1
,并验证得到的字符串中是否存在长度为5或6的回文子串,时间复杂度为\(O(n\cdot 2^n)\),这种方法能够通过小数据。下面主要介绍通过大数据的方法。
显然,暴力方法的时间复杂度为指数级,可以通过动态规划将时间复杂度降低到多项式级别。先进行分类讨论:如果S
长度小于5,那么该字符串无论怎么替换?
字符,都可以满足要求,直接输出POSSIBLE
即可;如果S
长度为5,那么可以暴力枚举所有可能得到的替换后的字符串,并验证该字符串是否为回文串即可;下面主要讨论S
长度大于5的情况。
设\(dp[i]\)表示以S
的前i
个字符能否找到一种替换方法保证没有长度大于等于5的回文子串。由于要验证是否包含长度为6的回文子串,那么在每次添加新的字符S[i]
时,S[i]
能否构成长度为6的回文子串与S[i]
前面的5个字符S[i-5],S[i-4],S[i-3],S[i-2],S[i-1]
有关,因此,可以为S[i]
的前5个字符标记一个状态,由于每个字符的取值只有0
和1
两种,因此状态总数为\(2^5\)。针对字符S[i]
,暴力枚举以S[i]
结尾的长度为6的子串的可能替换结果字符串j
,如果j
包含长度为5或6的回文子串,则不符合题目要求;否则\(dp[i][j]=dp[i-1][j']\),其中\(j'=S[i-6]+j[:5]\)。具体实现可参考代码。
复杂度
- 时间复杂度为\(O(2^K\cdot N)\)。
- 空间复杂度为\(O(2^K\cdot N)\)。
其中\(K=5\)。
C++代码
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
#define rep(i, a, b, c) for (gg i = (a); i <= (b); i += (c))
#define rrep(i, a, b, c) for (gg i = (a); i >= (b); i -= (c))
constexpr gg MAX = 1e5 + 5;
constexpr gg MAX2 = 70;
constexpr gg mod = 1e9 + 7;
constexpr gg INF = 4e18;
constexpr double eps = 1e-12;
gg ti, ni, mi, ki, di, pi, xi, yi;
gg up(gg n, gg m) { return n >= 0 ? (n + m - 1) / m : n / m; }
gg down(gg n, gg m) { return n >= 0 ? n / m : (n - m + 1) / m; }
//! ti; MAX; mod; 边界
bool dp[MAX][MAX2];
string s;
void dfs(gg p, gg r, string cur, vector<string>& v) {
if (p > r) {
v.push_back(cur);
return;
}
if (s[p] != '1') {
dfs(p + 1, r, cur + "0", v);
}
if (s[p] != '0') {
dfs(p + 1, r, cur + "1", v);
}
}
bool isPalic(const string& s) { return equal(s.begin(), s.end(), s.rbegin()); }
void solve() {
cin >> ni >> s;
if (ni <= 4) {
cout << "POSSIBLE";
} else if (ni == 5) {
vector<string> v;
dfs(0, 4, "", v);
bool ans = all_of(v.begin(), v.end(), isPalic);
cout << (ans ? "IMPOSSIBLE" : "POSSIBLE");
} else {
bool ans = false;
rep(i, 5, ni - 1, 1) {
vector<string> v;
dfs(i - 5, i, "", v);
for (string& k : v) {
gg cur = stoll(k, 0, 2);
dp[i][cur] = not(isPalic(k) or isPalic(k.substr(0, 5)) or isPalic(k.substr(1, 5)));
if (i >= 6) {
bool res = false;
if (s[i - 6] != '1') {
res = res or dp[i - 1][stoll("0" + k.substr(0, 5), 0, 2)];
}
if (s[i - 6] != '0') {
res = res or dp[i - 1][stoll("1" + k.substr(0, 5), 0, 2)];
}
dp[i][cur] = dp[i][cur] and res;
}
if (i == ni - 1) {
ans = ans or dp[i][cur];
}
}
}
cout << (ans ? "POSSIBLE" : "IMPOSSIBLE");
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ti = 1;
cin >> ti;
for (gg ii = 1; ii <= ti; ++ii) {
cout << "Case #" << ii << ": ";
solve();
cout << "\n";
}
return 0;
}
Interesting Integers
题意概述
如果一个整数的所有数字的乘积能被所有数字的和整除,就称这个整数为有趣的。给出两个整数\(A\)和\(B\),找出\([A,B]\)之间有趣的整数个数。
数据规模
\]
算法设计
目前只会解小数据,大数据的解法可参考Google Kick Start 2022 Round A 题解。通过枚举\([A,B]\)之间的数字,暴力判断组成该整数的所有数字的乘积能能否被所有数字的和整除即可。
复杂度
- 时间复杂度为\(O(n)\)。
- 空间复杂度为\(O(n)\)。
其中\(n=B-A+1\)。
C++代码
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
#define rep(i, a, b, c) for (gg i = (a); i <= (b); i += (c))
#define rrep(i, a, b, c) for (gg i = (a); i >= (b); i -= (c))
constexpr gg MAX = 1e5 + 5;
constexpr gg MAX2 = 70;
constexpr gg mod = 1e9 + 7;
constexpr gg INF = 4e18;
constexpr double eps = 1e-12;
gg ti, ni, mi, ki, di, pi, xi, yi;
gg up(gg n, gg m) { return n >= 0 ? (n + m - 1) / m : n / m; }
gg down(gg n, gg m) { return n >= 0 ? n / m : (n - m + 1) / m; }
//! ti; MAX; mod; 边界
bool func(gg n) {
gg s = 0, p = 1;
while (n > 0) {
s += n % 10;
p *= n % 10;
n /= 10;
}
return p % s == 0;
}
void solve() {
cin >> xi >> yi;
gg ans = 0;
rep(i, xi, yi, 1) {
if (func(i)) {
++ans;
}
}
cout << ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ti = 1;
cin >> ti;
for (gg ii = 1; ii <= ti; ++ii) {
cout << "Case #" << ii << ": ";
solve();
cout << "\n";
}
return 0;
}
Google kickstart 2022 Round A题解的更多相关文章
- google kickstart 2018 round D A Candies
思路: 对于small数据,由于求和及奇数数量两个限制条件均满足区间单调性,可以直接使用尺取法(滑动窗口法)求解. 对于large数据,奇数数量依然是满足区间单调性的.首先使用尺取法,找到所有满足奇数 ...
- Codeforces Round #556 题解
Codeforces Round #556 题解 Div.2 A Stock Arbitraging 傻逼题 Div.2 B Tiling Challenge 傻逼题 Div.1 A Prefix S ...
- LibreOJ β Round #2 题解
LibreOJ β Round #2 题解 模拟只会猜题意 题目: 给定一个长为 \(n\) 的序列,有 \(m\) 次询问,每次问所有长度大于 \(x\) 的区间的元素和的最大值. \(1 \leq ...
- Google Kickstart在线测试规则以及注意事项
谷歌招聘在如火如荼的进行中,进谷歌都需要经过谷歌kickstart在线测试,然后过了之后还有五轮的面试- -.好吧毕竟你待遇高,你强你有理.. 下面介绍一下进谷歌的第一关google kickstar ...
- Codeforces Round #569 题解
Codeforces Round #569 题解 CF1179A Valeriy and Deque 有一个双端队列,每次取队首两个值,将较小值移动到队尾,较大值位置不变.多组询问求第\(m\)次操作 ...
- Codeforces Round #557 题解【更完了】
Codeforces Round #557 题解 掉分快乐 CF1161A Hide and Seek Alice和Bob在玩捉♂迷♂藏,有\(n\)个格子,Bob会检查\(k\)次,第\(i\)次检 ...
- CFEducational Codeforces Round 66题解报告
CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第 ...
- Google Kick Start Round G 2019
Google Kick Start Round G 2019 Book Reading 暴力,没啥好说的 #include<bits/stdc++.h> using namespace s ...
- PKUSC 2022 口胡题解
\(PKUSC\ 2022\)口胡题解 为了更好的在考试中拿分,我准备学习基础日麻知识(为什么每年都考麻将 啊啊啊) 首先\(STO\)吉老师\(ORZ,\)真的学到了好多 观察标签发现,这套题覆盖知 ...
随机推荐
- 各种环境下反弹shell
0x00 NC命令详解 在介绍如何反弹shell之前,先了解相关知识要点. nc全称为netcat,所做的就是在两台电脑之间建立链接,并返回两个数据流 可运行在TCP或者UDP模式,添加参数 -u 则 ...
- position 的值absolute、fixed、relative和static的定位原点是什么
position 的值absolute.fixed.relative和static的定位原点是什么 absolute 成绝对定位的元素,相对于值不为static的第一个父元素进行定位,也可以理解为离自 ...
- 重写hashcode和equals方法
重写hashcode和equals方法 简乐君 2019-05-07 21:55:43 35481 收藏 191分类专栏: Java 文章标签: equals() hashcode()版权 一.前言我 ...
- Scanner几个问题与正则简介
Pre:最近做了头条的在线笔试,对Scanner输入的处理有些特殊,当时是一脸懵逼态,遂由此随笔(/@_@\),java小白,有错难免! 查了下Scanner的源码,没有头绪,但是其中用到了正则的知识 ...
- springboot使用策略模式实现一个基本的促销
策略模式 定义了算法族,分别封装起来,让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户 源码:https://github.com/youxiu326/sb_promotion.git ...
- ACM - 动态规划 - UVA323 Jury Compromise
UVA323 Jury Compromise 题解 考虑用动态规划.该问题要求解的最终状态为,选出的 \(m\) 个人,使得辩方总分与控方总分差的绝对值最小,总分之和最大.即 \(\left| D(\ ...
- 13_Invariance Principle_LaSalle's Theorem_不变性原理
- android:text 文字阴影设置
<SPAN style="FONT-SIZE: 16px"><TextView android:id="@+id/text" a ...
- python-排列组合序列
[题目描述]用户输入整数n(1<=n<=26)和整数m(m<=n),然后输入n个不同的字母,请编写程序输出在这n个字母中选择m个字母的所有排列序列和组合序列. [练习要求]请给出源代 ...
- java中什么叫多重捕获MultiCatch,它的用法是怎样的?
2.多重捕获MultiCatch 马克-to-win:什么叫多重捕获MultiCatch?一段代码可能引起多个异常,这时可以定义两个或更多的catch子句来处理这种情况,每个子句捕获一种类型的异常.马 ...