比赛链接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. shell编程基础知识

    什么是shell shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出屏幕返回给用户 shell对话方式 交互的方 ...

  2. WebViewJavascriptBridge(H5与原生交互)

    https://github.com/wangjiaojiao77/WebViewJavascriptBridge(IOS)和 https://github.com/wangjiaojiao77/Js ...

  3. 【16】LRUChache

    题目 LRU 思路 LRU 大家都不陌生,操作系统的作业做过,思路就是一旦添加或者访问某个元素,则将其的"访问属性"置零,而其他元素的访问属性统统减一,这样一来,访问属性最小的元素 ...

  4. C++——简单程序设计

    1.一个简单的程序 #include <iostream> //iostream是头文件,用来说明要使用的对象的相关信息. using namespace std; //使用命名空间,解决 ...

  5. jquery+layer实现无刷新、删除功能(laravel框架)

    先来看一下效果 路由代码 Route::get('car/{id}/delete', 'CarController@delete'); 控制器层代码 //删除汽车信息 public function ...

  6. UIgradients – 美丽的UI渐变色分享站 并可转成CSS代码

    前期我们分享了「如何使用彩色滤镜创造奇妙的网页设计」这篇文章,通过渐变彩色滤镜实现很多漂亮的效果,然而用什么渐变颜色才好呢?可以看看今天为大家分享的 UIgradients 渐变色分享网站,里面有很多 ...

  7. js处理json字符串

    后台输出的字符串为 res= {"result":"true","data":"提交成功"} 前台js无法转化成对象,需 ...

  8. Java+Selenium+Testng自动化测试学习(四)— 报告

    自动化测试报告,在测试用例完成之后系统自动生成HTML报告 使用testng中的报告模板生成报告, 1.在TestSuit.xml文件中配置报告监听 2.运行xml文件 3.自动生成一个test-ou ...

  9. Java-POJ1010-STAMP

    说良心话,题目不难,但是题目真的很不好懂,解读一下吧 题意: 读入分两行,第一行为邮票面额(面额相同也视为种类不同)以0结束,第二行为顾客要求的面额,以0结束 要求:每个顾客最多拿4张邮票,并求最优解 ...

  10. 计算系数(NOIP2011提高LuoguP1313)

    一道数论好题,知识点涉及扩展欧几里得,快速幂,逆元,二项式定理,模运算,组合数等. (别问为啥打了快速幂不用费马小求逆元...我就练习下扩欧) (数据就应该再加大些卡掉n^2递推求组合数的) #inc ...