比赛链接https://codeforc.es/contest/1202

 

A. You Are Given Two Binary Strings...

题意:给出两个二进制数\(f(x)\)和\(f(y)\),定义一个二进制数\(s_k=f(x)+2^k\cdot f(y)\),询问\(k\)取何值时\(s_k\)的反向字符串(将二进制数看作01串)字典序最小。

分析:首先,我们需要知道对于一个二进制数乘2,相当于将该数整体左移一位,因此我们只需要找到\(f(y)\)最右侧的1的位置\(pos\),令它去和\(f(x)\)在\(pos\)左侧最近的\(y\)匹配,这样得到的反向字符串字典序必然最小。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll n, m, t;
string s1, s2;
int main() {
io(); cin >> t;
while(t--) {
cin >> s1 >> s2;
int len1 = s1.length() - 1, len2 = s2.length() - 1;
n = 0;
while(s2[len2--] == '0') ++n;
m = n;
while(s1[len1 - m] == '0') ++m;
cout << m - n << endl;
}
}

 

B. You Are Given a Decimal String...

题意:不是很讲得清楚,可以看题中样例理解。给出一个字符串字符串中的每一位数字由确定的两个数字任意组合得到,询问,为了得到该字符串,最少需要多构成几个无效数字。例如:

给出字符串\(0840\),确定的两个数字为\((2, 4)\)。

  1. 0 (初始必定为零)
  2. 04 (\(+4\))
  3. 048 (\(+4\))
  4. 0482 (\(+4\),如果超过10就只取个位数)
  5. 04824 (\(+2\))
  6. 048248 (\(+4\))
  7. 0482480 (\(+2\))

于是,(0) 4 (8) 2 (4) 8 (0),多生成的数的个数为3。

分析:从字符串第\(k\)位到\(k+1\)位实际上相当于变化了\(\vert s_{k+1}-s_k \vert\),这个值不会超过10,因此我们只需要暴力求出这10种情况所生成的无效数字个数即可。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
const int maxn = 1e9;
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
int n, m, t; int dp[10];
string s;
int main() {
io(); cin >> s;
int len = s.length();
rep(i, 0, 9) {
rep(j, 0, 9) {
rep(k, 0, 9) dp[k] = maxn;
rep(x, 0, 9) {
rep(y, 0, 9) {
if (!x && !y) continue;
dp[(x * i + y * j) % 10] = min(x + y - 1, dp[(x * i + y * j) % 10]);
}
}
int ans = 0;
rep(k, 0, len - 2) {
int tmp = s[k + 1] - s[k];
if (dp[(tmp + 10) % 10] == maxn) { ans = -1; break; }
ans += dp[(tmp + 10) % 10];
}
cout << ans << ' ';
}
cout << endl;
}
}

 

C. You Are Given a WASD-string...

题意:T组输入,每组输入给出一个只含“\(W, A, S, D\)”的字符串(又是字符串...)。\(W, A, S, D\)分别代表一个机器人可以向上,左,下,右四个方向移动一格。定义机器人走过的面积为能包含所有机器人走到过的格子的最小面积。现在,你能在字符串中的任意位置加入一个字符(只能为\(W, A, S, D\)),询问可能的机器人走过的最小面积。

分析:由于只能加入一个字符,所以我们发现横向的移动和纵向移动互不干扰(最小矩形只能是长或者宽缩进一个单位),因此我们只需要分成横向纵向两个子问题考虑,并找到最小面积即可。我用了一种前缀和的思想写,而标程给出了更简洁的解法。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
int n, m, t;
string str;
struct node {
int val;
int pos;
int la, lb, ra, rb;
}p1[SIZE], p2[SIZE];
void init1(node p[], int n) {
int x = INF, y = -INF;
rep(i, 0, n) {
p[i].la = min(x, p[i].pos);
x = min(x, p[i].la);
p[i].ra = max(y, p[i].pos);
y = max(y, p[i].ra);
}
}
void init2(node p[], int n) {
int x = INF, y = -INF;
for (int i = n; i >= 0; --i) {
p[i].lb = min(x, p[i].pos);
x = min(x, p[i].lb);
p[i].rb = max(y, p[i].pos);
y = max(y, p[i].rb);
}
}
int main() {
io(); cin >> t;
while (t--) {
cin >> str;
int k = 1, j = 1;
rep(i, 0, str.length() - 1) {
if (str[i] == 'W') p1[k++].val = 1;
else if (str[i] == 'S') p1[k++].val = -1;
else if (str[i] == 'A') p2[j++].val = 1;
else p2[j++].val = -1;
}
rep(i, 0, k - 1) p1[i].pos = p1[i - 1].pos + p1[i].val;
rep(i, 0, j - 1) p2[i].pos = p2[i - 1].pos + p2[i].val;
init1(p1, k - 1); init1(p2, j - 1);
init2(p1, k - 1); init2(p2, j - 1);
ll w = p1[k - 1].ra, a = p2[j - 1].la, s = p1[k - 1].la, d = p2[j - 1].ra;
ll h = p1[k - 1].ra - p1[k - 1].la + 1, wid = p2[j - 1].ra - p2[j - 1].la + 1;
bool f1 = false, f2 = false;
rep(i, 0, k - 1) {
if (p1[i].lb < p1[i].la && p1[i].rb < p1[i].ra) { f1 = true; break; }
if (p1[i].lb > p1[i].la && p1[i].rb > p1[i].ra) { f1 = true; break; }
}
rep(i, 0, j - 1) {
if (p2[i].lb < p2[i].la && p2[i].rb < p2[i].ra) { f2 = true; break; }
if (p2[i].lb > p2[i].la && p2[i].rb > p2[i].ra) { f2 = true; break; }
}
if (f1 || f2) {
if (f1 && f2) {
if (wid > h) cout << wid * (h - 1) << endl;
else cout << (wid - 1) * h << endl;
continue;
}
if (f1) cout << wid * (h - 1) << endl;
else cout << (wid - 1) * h << endl;
}
else cout << wid * h << endl;
}
}

 

D. Print a 1337-string...

题意:给出一个正整数\(n\),构造一个含有\(n\)个\(1337\)子串的字符串(还是字符串...)。

分析:我们考虑每次构造\(C_n^2\)个直到完成例如 \(10=6+3+1\),那么我们就能构造出\(13373737\)。但要注意最后可能会剩下2,可是不能重复构造两次1。因此最后为2的构造我们在倒数第三位插入两个1,例如:\(8=6+2\) 构造出:\(13311337\)。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll n, m, t; bool flag;
ll dp[SIZE];
vector<int> v;
int main() {
io(); cin >> t;
rep(i, 1, 100050) dp[i] = 1ll * i * (i - 1) / 2;
while (t--) {
cin >> n; m = n; v.clear();
if (n == 2) { cout << "11337\n"; continue; }
flag = false;
while (n) {
int pos = lower_bound(dp, dp + 100010, n) - dp;
if (dp[pos] > n) --pos;
n -= dp[pos];
v.emplace_back(pos);
if (n == 2) { flag = true; break; }
}
int cnt = 1, it = v.size() - 1;
cout << "13";
while (cnt < v[0]) {
if (flag && cnt == v[0] - 2) cout << "11";
if (cnt < v[it]) cout << 3;
else { --it, --cnt; cout << 7; }
cnt++;
}
cout << "7\n";
}
}

 

E. You Are Given Some Strings...

题意:先给出一个字符串\(t\)(全是字符串...),再给出\(n\)个字符串\(s1, s2, ..., s_n\)。定义函数\(f(t, s)\)为求出字符串\(s\)在\(t\)中的出现次数,例如:\(f(aaabacaa, aa)=3\)。现在要求出\(\sum_{i=1}^{n}\sum_{j=1}^{n}f(t, s_i+s_j)\)的值。

分析:我们考虑如果\(t\)串中存在\(s_i+s_j\)那么必然存在一个位置\(pos\)满足\(pos\)前面为后缀串\(s_i\),\(pos\)后面为前缀串\(s_j\),因此我们只需要对每一个\(pos\)跑出前缀串和后缀串的数量,乘法原理累加即可。而前缀串后缀串计数的操作只需要正反跑两次AC自动机即可。

AC代码

#include <bits/stdc++.h>
#define SIZE 200010
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
struct ACAM {
int cnt, trie[SIZE][26], fail[SIZE], q[SIZE], sum[SIZE], h, r, num[SIZE];
void insert(char s[], int n) {
int now = 0;
rep(i, 1, n) {
int p = s[i] - 'a';
if (!trie[now][p]) trie[now][p] = ++cnt;
now = trie[now][p];
}
sum[now]++;
}
void build() {
h = 1; r = 0;
rep(i, 0, 25) if (trie[0][i]) q[++r] = trie[0][i];
while (h <= r) {
int u = q[h++];
rep(i, 0, 25) {
if (trie[u][i]) {
fail[trie[u][i]] = trie[fail[u]][i];
sum[trie[u][i]] += sum[fail[trie[u][i]]];
q[++r] = trie[u][i];
}
else trie[u][i] = trie[fail[u]][i];
}
}
}
void solve(char s[], int n) {
int now = 0;
rep(i, 1, n) {
int p = s[i] - 'a';
now = trie[now][p];
num[i] = sum[now];
}
}
}AC[2];
int n, len;
char s[SIZE], t[SIZE], rs[SIZE], rt[SIZE];
int main() {
io(); cin >> (t + 1) >> n;
rep(i, 1, n) {
cin >> (s + 1);
len = strlen(s + 1);
for (int i = len; i; --i) rs[len - i + 1] = s[i];
AC[0].insert(s, len);
AC[1].insert(rs, len);
}
len = strlen(t + 1);
for (int i = len; i; --i) rt[len - i + 1] = t[i];
AC[0].build(); AC[1].build();
AC[0].solve(t, len); AC[1].solve(rt, len);
ll ans = 0;
rep(i, 1, len) ans += 1ll * AC[0].num[i] * AC[1].num[len - i];
cout << ans;
}

 

F. You Are Given Some Letters...

题意:给出两个正整数\(a\)代表\(A\)字符的数量,\(b\)代表\(B\)字符的数量,构造一个字符串(Stringforces...),使得字符串由某一循环节或循环节中的部分构成的,询问最多能找出几组能完成上述构造的不同循环节(仅长度不同的循环节被视作不同的)。

分析:我们首先把问题转化为数学形式。先设一个循环节的长度为\(k\),那么该循环节完整出现的次数\(n\)的表达式即为\(n=\lfloor \frac{a+b}{k} \rfloor\)。

同时,我们假设该循环节中\(A\)出现的次数为\(num_a\),\(B\)为\(num_b\),显然有\(num_a+num_b=k\)。并且我们可以得到下列不等式组:$$0 \leq a-n \cdot num_a \leq num_a$$ $$0 \leq b-n \cdot num_b \leq num_b$$

转化后得到:$$\lceil \frac{a}{n+1} \rceil \leq num_a \leq \lfloor \frac{a}{n} \rfloor$$ $$\lceil \frac{b}{n+1} \rceil \leq num_a \leq \lfloor\frac{b}{n} \rfloor$$

于是,我们得到了\(num_a\)和\(num_b\)的范围,当且仅当\(num_a\)和\(num_b\)均存在时,我们才可以满足条件的循环节。因此,我们不妨枚举循环节出现次数\(n\)的值,通过求得的\(num_a\)和\(num_b\)的存在范围来求解。

显然每次枚举,我们都应该将答案加上\(num_{amax}+num_{bmax}-num_{amin}-num_{bmin}+1\),即\(\lceil \frac{a}{n+1} \rceil + \lceil \frac{b}{n+1} \rceil - \lfloor \frac{a}{n} \rfloor - \lfloor \frac{b}{n} \rfloor + 1\),但要注意我们枚举了\(n\)的值,因此\(k\)是有范围的,\(\frac{a+b}{n+1} \leq k < \frac{a+b}{n}\)。时间复杂度\(o(\sqrt{n})\)。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll a, b;
string s;
int main() {
io(); cin >> a >> b;
ll ans = 0;
for (ll i = 1; i <= a + b;) {
ll n = (a + b) / i;
ll maxr = (a + b) / n;
if (n > a || n > b) { i = (a + b) / n + 1; continue; }
ll l = ceil(1.0*a / (n + 1)), r = a / n;
ll L = ceil(1.0*b / (n + 1)), R = b / n;
if (l <= r && L <= R) ans += max(0ll, min(maxr, r + R) - max(i, l + L) + 1);
i = maxr + 1;
}
cout << ans;
}

Educational Codeforces Round 70 (Rated for Div. 2) 题解的更多相关文章

  1. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  2. Educational Codeforces Round 65 (Rated for Div. 2)题解

    Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...

  3. Educational Codeforces Round 64 (Rated for Div. 2)题解

    Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...

  4. Educational Codeforces Round 60 (Rated for Div. 2) 题解

    Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...

  5. Educational Codeforces Round 58 (Rated for Div. 2) 题解

    Educational Codeforces Round 58 (Rated for Div. 2)  题目总链接:https://codeforces.com/contest/1101 A. Min ...

  6. Educational Codeforces Round 70 (Rated for Div. 2)

    这次真的好难...... 我这个绿名蒟蒻真的要崩溃了555... 我第二题就不会写...... 暴力搜索MLE得飞起. 好像用到最短路?然而我并没有学过,看来这个知识点又要学. 后面的题目赛中都没看, ...

  7. n=C(2,n)+k(构造)( Print a 1337-string)Educational Codeforces Round 70 (Rated for Div. 2)

    题目链接:https://codeforc.es/contest/1202/problem/D 题意: 给你一个数 n ( <=1e9 ),让你构造137713713.....(只含有1,3,7 ...

  8. (模拟)关于进制的瞎搞---You Are Given a Decimal String...(Educational Codeforces Round 70 (Rated for Div. 2))

    题目链接:https://codeforc.es/contest/1202/problem/B 题意: 给你一串数,问你插入最少多少数可以使x-y型机器(每次+x或+y的机器,机器每次只取最低位--% ...

  9. Educational Codeforces Round 47 (Rated for Div. 2) 题解

    题目链接:http://codeforces.com/contest/1009 A. Game Shopping 题目: 题意:有n件物品,你又m个钱包,每件物品的价格为ai,每个钱包里的前为bi.你 ...

随机推荐

  1. python之路模块简介及模块导入

    ================================添加sys.path路径================================================== ===== ...

  2. 巨杉Tech | 微服务趋势下的数据库设计与应用简析

    周五(7月12日)巨杉数据库参与了由得到App主办八里庄技术沙龙活动,分享主题是关于分布式数据库架构与实战. 以下就是根据巨杉数据库现场分享的内容进行的分享实录整理. 巨杉数据库简介 巨杉,专注新一代 ...

  3. Python 编辑注意点

    文本编辑 Python: 绝对不能用Word和Windows自带的记事本. (1)Word保存的不是纯文本文件 (2)记事本会自作聪明地在文件开始的地方加上几个特殊字符(UTF-8 BOM),结果会导 ...

  4. Android 开发压缩图片

    private Bitmap imageZoom(int position , Bitmap bitMap) {        //图片允许最大空间         double maxSize =2 ...

  5. root xshell登陆Ubuntu

    https://www.jianshu.com/p/c8ee39488d2a xshell测试非root用户,可以正常连接,但是root用户仍旧无法访问 解决方法:修改 /etc/ssh/sshd_c ...

  6. h264 RTP STAP-A单时间聚合包

    参考官方文档:http://www.rosoo.net/Files/UpFiles/RsProduct/avtools/2009-4/2009491562537854.txt 聚合包的RTP荷载格式的 ...

  7. 【新特性速递】F.doPostBack的说明文档

    FineUIPro/Mvc/Core的下个版本(v6.1.0),我们对客户端JS函数 F.doPostBack 进行了增强,并增加说明文档. 如果你还没有查阅过FineUI的客户端文档,可以收藏下这个 ...

  8. mysql(3):锁和事务

    MySQL锁的介绍 锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访问. 表级锁 例如MyISAM引擎,其锁是表锁设计.并发情况下的读没有问题,但是并发插入时的性能要差一些 ...

  9. spring(四):Resource

    Resource Spring的Resource接口代表底层外部资源,提供了对底层外部资源的一致性访问接口. public interface Resource extends InputStream ...

  10. Solr与JDK对应版本关系,Tomcat与JDK版本对应关系

    最新在部署solrCloud集群,由于自己机器上用的JDK都是JDK1.7的,然后我就从网上下载了最新下载了最先的solr6.6.0和最新的Tomcat9.0,部署了一下,开始报错,提示solr和JD ...