比赛链接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. Windwos查看本地局域网内所有的ip方法

    Windows平台ping测试局域网所有在用IP .打开cmd命令窗口 .输入命令:,,) DO ping -w -n .%i //这个是自己局域网的ip地址前三位 查看自己ip信息的命令是ipcon ...

  2. SQL Server查询中特殊字符的处理方法 (SQL Server特殊符号的转义处理)

    SQL Server查询中特殊字符的处理方法 (SQL Server特殊符号的转义处理) SQL Server查询中,经常会遇到一些特殊字符,比如单引号'等,这些字符的处理方法,是SQL Server ...

  3. Spring解决bean之间的循环依赖

    转自链接:https://blog.csdn.net/lyc_liyanchao/article/details/83099675通过前几节的分析,已经成功将bean实例化,但是大家一定要将bean的 ...

  4. Jquery 如何设置多个attr()属性

    Jquery 如何设置多个attr()属性?     文章来源:刘俊涛的博客 欢迎关注公众号.留言.评论,一起学习. _________________________________________ ...

  5. 获取 Android APP 版本信息工具类(转载)

    获取 Android APP 版本信息工具类 获取手机APP版本信息工具类 1.获取版本名称 2.获取版本号 3.获取App的名称 package com.mingyue.nanshuibeidiao ...

  6. hrtf 旋转音效matlab实现

    原理参考: http://www.mahong.me/archives/97 将音频分段,各个段分别使用hrtf在Ls, L, R, Ls, Rrs, Lrs位置处的filter系数.是声音听起来来自 ...

  7. OrCAD 仿真与仿真模块库介绍

    PSpice A/D9.1个别时候可能会出现异常现象,例如:某一步后,突然电路图的电源极性被自动改变了!造成直流电压和直流电流不正常,输出无波形.所以应该趁正常的时候做好备份是明智的. PSpice ...

  8. CentOS 7升级gcc版本

    Centos 7默认gcc版本为4.8,有时需要更高版本的,这里以升级至8.3.1版本为例,分别执行下面三条命令即可,无需手动下载源码编译 1.安装centos-release-scl sudo yu ...

  9. 使用VSCode的Remote-SSH连接Linux进行远程开发

    安装Remote-SSH并配置 首先打开你的VSCode,找到Extensions,搜索Remote,下载Remote-Developoment插件,会自动安装其他的Remote插件,其中会包含Rem ...

  10. vga显示原理即相关计算

    行扫描周期:完成一行扫描所需时间: 行时序时间(a,b,c,d,e):完成一个像素点显示得时间 场扫描周期:完成所有行(一帧扫描所需时间) 场时序时间(o,p,q,r,s):完成一行显示得时间,一个完 ...