比赛链接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. AntDesign(React)学习-8 Menu使用 切换框架页内容页面

    本节实现一个点击左侧menu在右侧content切换页面效果,原始代码请从UMI学习-6开始看 1.在pages下添加两个组件,User,UserRole import React from 'rea ...

  2. 'ssh-keygen' 不是内部或外部命令,也不是可运行的程序

    右键我的电脑,点击环境变量,设置系统配置里面的Path 新增一个 D:\ruanjiananzhuangdizhi\Git\usr\bin 路径就可以了

  3. Qt中的Label和PushButton背景图自动缩放设置

    Label 背景图自动缩放 QPixmap* pixmap = new QPixmap(":/images/HeadIcon/1.png"); pixmap->scaled( ...

  4. [JZOJ4899] 雪之国度

    题目描述 雪之国度有N座城市,依次编号为1到N,又有M条道路连接了其中的城市,每一条道路都连接了不同的2个城市,任何两座不同的城市之间可能不止一条道路.雪之女王赋予了每一座城市不同的能量,其中第i座城 ...

  5. NG-ALAIN 边学边记2

    1. 下载Git上的源码  : https://github.com/ng-alain/ng-alain.git 2.解压文件: 3.进入到目录下: 4.打开CMD 切换到 E:\NgAlain\ng ...

  6. 2019牛客多校第五场 F maximum clique 1 状压dp+最大独立集

    maximum clique 1 题意 给出一个集合s,求每个子集的最大独立集的权值和(权值是独立集的点个数) 分析 n比较小,一股浓浓的暴力枚举每一个子集的感觉,但是暴力枚举模拟肯定会T,那么想一想 ...

  7. pygame 浅解

    import pygame from first_pygame.plane_spirit import * # 调用重载的精灵类 # 初始化 pygame.init() # 初始化所有所需游戏模块 s ...

  8. 持续集成与自动化部署---代码流水线管理及Jenkins和gitlab集成

    1.代码流水线管理 Pipeline名词顾名思义就是流水线的意思,因为公司可能会有很多项目.如果使用jenkins构建完成后,开发构建项目需要一项一项点击,比较麻烦.所以出现pipeline名词. 代 ...

  9. MYSQL入门总结

    创建数据库及创建表 create schema/database ttest(名字); //创建数据库 create table ttest(建好的数据库名字).new_table(表名字) ( a ...

  10. WPF页面切换

    XAML <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft. ...