Codeforces Round #609 (Div. 2)前五题题解
Codeforces Round #609 (Div. 2)前五题题解
补题补题……
C题写挂了好几个次,最后一题看了好久题解才懂……我太迟钝了……
然后因为longlong调了半个小时……
A.Equation
题目大意:有一个数字n,让你给出任意两个合数a,b满足a - b = n。
我们知道大于2的偶数都是合数,那么如果n为奇数,只要n加上一个奇数合数一定也为合数,如果n为偶数,那么n加上一个偶数合数也一定为合数。
因为只求任意一组,就直接选择4,9,若为奇数输出 +n 和9,偶数输出 +n 和4。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(x, l, r) for(int x = l; x <= r; x++)
#define repd(x, r, l) for(int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define all(x) x.begin(), x.end()
#define pb push_back
#define mp make_pair
#define MAXN
#define fi first
#define se second
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
const int INF = << ;
const int p = ;
int lowbit(int x){ return x & (-x);}
int fast_power(int a, int b){ int x; for(x = ; b; b >>= ){ if(b & ) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;} int main(){
int n;
scanf("%d", &n);
if(n % ) printf("%d %d\n", n + , );
else printf("%d %d\n", n + , );
return ;
}
B.Modulo Equality
题目大意:有两个长为n的数列a和b,现在让你给a中每个数加上一个数x并对m取模,并重新排列,使得两数列相同。求最小的x。
很明显x一定是在 (a1 - bi + m) mod m 中的一个数,我们只要枚举这个数,判断和数列b是否相同即可。
n最大只有2000,为了方便(我比较懒),判断相同时可以直接将a重新排序后判断,不会超时。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(x, l, r) for(int x = l; x <= r; x++)
#define repd(x, r, l) for(int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define all(x) x.begin(), x.end()
#define pb push_back
#define mp make_pair
#define MAXN 2005
#define fi first
#define se second
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
const int INF = << ;
const int p = ;
int lowbit(int x){ return x & (-x);}
int fast_power(int a, int b){ int x; for(x = ; b; b >>= ){ if(b & ) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;} int a[MAXN], b[MAXN], c[MAXN]; int main(){
int n, m;
scanf("%d%d", &n, &m);
rep(i, , n) scanf("%d", &a[i]);
rep(i, , n) scanf("%d", &b[i]);
sort(a + , a + n + );
sort(b + , b + n + );
int ans = INF;
rep(i, , n){
int res = (b[] - a[i] + m) % m;
rep(j, , n) c[j] = (a[j] + res) % m;
sort(c + , c + n + );
bool flag = ;
rep(j, , n)
if(c[j] != b[j]){
flag = ;
break;
}
if(flag) ans = min(ans, res);
}
printf("%d\n", ans);
return ;
}
C.Long Beautiful Integer
题目大意:给你一个数字x,以及正整数k,求一个大于等于x的最小数字y并满足 yi = yi + k ( <= i <= n - k) 。n为x的长度,n小于等于500.
这一题hack数据还真多,197组……
首先可以发现,数字y的长度一定是等于x的长度的,因为全为9的数字一定满足条件。
对于 yi = yi + k 这个式子,我们发现,对于所有位置i对k取模结果相同的,该位上的数字也一定是相同的。
那我们只要枚举最后前k位数字即可,为了让数字尽量小,我们让y的每一位和x一样大,然后判断此时y和x的大小。
若y大于等于x,那么y就是答案。若y小于x,只需要在第k位加上1即可。
注意:需要进位!!!
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(x, l, r) for(int x = l; x <= r; x++)
#define repd(x, r, l) for(int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define all(x) x.begin(), x.end()
#define pb push_back
#define mp make_pair
#define MAXN 200005
#define fi first
#define se second
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
const int INF = << ;
const int p = ;
int lowbit(int x){ return x & (-x);}
int fast_power(int a, int b){ int x; for(x = ; b; b >>= ){ if(b & ) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;} int num[MAXN], ans[MAXN];
char st[MAXN]; int main(){
int n, m;
scanf("%d%d", &n, &m);
scanf("%s", st);
int maxx = ;
rep(i, , n){
num[i] = st[i - ] - '';
maxx = max(maxx, num[i]);
}
int minx = INF, miny = INF;
rep(i, , m){
ans[i] = num[i];
for(int j = i ; j <= n; j += m){
if(ans[i] < num[j]) minx = min(minx, j);
if(ans[i] > num[j]) miny = min(miny, j);
}
}
if(miny > minx){
ans[m] = num[m] + ;
for(int x = m; x > && ans[x] == ; x--){
ans[x] = ;
ans[x - ]++;
}
}
printf("%d\n", n);
rep(i, , n) printf("%d", ans[(i - ) % m + ]);
puts("");
return ;
}
D.Domino for Young
题目大意:有一个不规则的网格长为n,第i列有 ai ,现在用1×2的骨牌覆盖它,求最多能放多少个骨牌。
这题是我人生第一道秒掉的D题!!!
一看题目,这不是《组合数学》第一章的例题嘛,虽然有点差别,但是思路基本一模一样。
先讲一下组合那道题,就是说有一个n×m的网格(n和m为偶数),将它的左上角和右下角两个格子去掉,证明用1×2的骨牌覆盖它,没有一种方法能将它完美覆盖。
这道题目就是0,1染色,对相邻的节点染上不同的颜色,如图所示。
每一个骨牌只能覆盖一个0和一个1,而这张图中一共有12个1和10个0,不合。
那么回到这一题,我们也可以将这个网格进行黑白染色,每一个骨牌也是只能覆盖一个0和一个1,那么在最优的覆盖方案中,覆盖完了0和1中较少的。答案就是0的个数和1的个数的最小值。
另外统计0,1个数就不多说了,详见代码。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(x, l, r) for(int x = l; x <= r; x++)
#define repd(x, r, l) for(int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define all(x) x.begin(), x.end()
#define pb push_back
#define mp make_pair
#define MAXN 200005
#define fi first
#define se second
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
const int INF = << ;
const int p = ;
int lowbit(int x){ return x & (-x);}
int fast_power(int a, int b){ int x; for(x = ; b; b >>= ){ if(b & ) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;} int num[MAXN], ans[MAXN];
char st[MAXN]; int main(){
int n, m;
scanf("%d%d", &n, &m);
scanf("%s", st);
int maxx = ;
rep(i, , n){
num[i] = st[i - ] - '';
maxx = max(maxx, num[i]);
}
int minx = INF, miny = INF;
rep(i, , m){
ans[i] = num[i];
for(int j = i ; j <= n; j += m){
if(ans[i] < num[j]) minx = min(minx, j);
if(ans[i] > num[j]) miny = min(miny, j);
}
}
if(miny > minx){
ans[m] = num[m] + ;
for(int x = m; x > && ans[x] == ; x--){
ans[x] = ;
ans[x - ]++;
}
}
printf("%d\n", n);
rep(i, , n) printf("%d", ans[(i - ) % m + ]);
puts("");
return ;
}
E.K Integers
题目大意:有一数列p,长度为n。求最少的交换两个相邻数字的操作,使得数列p中存在连续子序列1,2,..., i 。其中i为1,2,..., n 。
这题大概一看就和逆序对有关,因为这个交换相邻操作和冒泡排序一模一样,而冒泡需要的操作就是逆序对的个数。
不难得出,当 i = n 时,答案就是逆序对个数。
对于其它的 i 来说,我们也可以得到这样一个贪心思想,先将1..i 放到一起,然后再将它们变成有序的。
变成有序的需要的操作很显然也可以按照 i = n 来做,但是将1..i 要放到哪里去呢?
根据初中学习的零点分段法,不知道的可以去看百度百科(传送门)了解一下。
最后将它们移到1..n在原数列中的中间一个位置(为了方便,后文用 mid 表示),一定是最优的,这可以用二分查找来实现。
至于它们需要移动多少呢?这要分成左右两段来算。
首先 mid 左边的全部移到中点,我们假设它们一共有 x 个,那么它们分别会被移到 mid - x , mid - x + ,..., mid - 。需要移动的操作个数分别要减去它们在数列中的位置,总答案就是要减去它们的总和 sum ,这可以用线段树或树状数组维护。得出以下的式子。
ans = mid - x + mid - x + 1 + ... + mid - 1 - sum = mid • x - sum - x • (x + 1) / 2;
注意,在代码中为了方便x包含了在 mid 点上的点,所以变成了 mid • x - sum - x • (x - ) / 。
另外在右边也是差不多,得出式子为 ans = sum - mid • x - x • (x + ) / 。
代码中还有以下几个注意点:
1.其实当 i = n 的时候也是可以用上一个式子算的,后面两个值都为0,你可以手算一下。
2.需要两个树状数组,一个维护前缀和(当然也可以用归并排序并加一些记录,但是比较长),一个维护上述的 sum 。
3.要开longlong!要开longlong!!要开longlong!!!重要的事情说三遍。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(x, l, r) for(int x = l; x <= r; x++)
#define repd(x, r, l) for(int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define all(x) x.begin(), x.end()
#define pb push_back
#define mp make_pair
#define MAXN 200005
#define fi first
#define se second
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
const int INF = << ;
const int p = ;
int lowbit(int x){ return x & (-x);}
int fast_power(int a, int b){ int x; for(x = ; b; b >>= ){ if(b & ) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;} int n;
int a[MAXN], pos[MAXN];
ll tree0[MAXN], tree1[MAXN]; void update0(int x, int y){
for(int i = x; i <= n; i += lowbit(i)) tree0[i] += y;
} void update1(int x, int y){
for(int i = x; i <= n; i += lowbit(i)) tree1[i] += y;
} ll query0(int x){
ll res = ;
for(int i = x; i > ; i -= lowbit(i)) res += tree0[i];
return res;
} ll query1(int x){
ll res = ;
for(int i = x; i > ; i -= lowbit(i)) res += tree1[i];
return res;
} int main(){
scanf("%d", &n);
rep(i, , n){
scanf("%d", &a[i]);
pos[a[i]] = i;
}
ll res0 = ;
rep(i, , n){
res0 += i - - query0(pos[i]);
update0(pos[i], );
update1(pos[i], pos[i]);
int l = , r = n, s;
while(l <= r){
int mid = (l + r) >> ;
if(query0(mid - ) * <= i){
s = mid;
l = mid + ;
}
else r = mid - ;
}
ll left_sum0 = query0(s), left_sum1 = query1(s);
ll res1 = left_sum0 * s - left_sum1 - left_sum0 * (left_sum0 - ) / ;
ll right_sum0 = i - left_sum0, right_sum1 = query1(n) - left_sum1;
res1 += right_sum1 - right_sum0 * s - right_sum0 * (right_sum0 + ) / ;
printf("%lld ", res0 + res1);
}
puts("");
return ;
}
Codeforces Round #609 (Div. 2)前五题题解的更多相关文章
- Lyft Level 5 Challenge 2018 - Final Round (Open Div. 2) (前三题题解)
这场比赛好毒瘤哇,看第四题好像是中国人出的,怕不是dllxl出的. 第四道什么鬼,互动题不说,花了四十五分钟看懂题目,都想砸电脑了.然后发现不会,互动题从来没做过. 不过这次新号上蓝名了(我才不告诉你 ...
- BestCoder Round #11 (Div. 2) 前三题题解
题目链接: huangjing hdu5054 Alice and Bob 思路: 就是(x,y)在两个參考系中的表示演全然一样.那么仅仅可能在这个矩形的中点.. 题目: Alice and Bob ...
- Codeforces Round #460 (Div. 2) 前三题
Problem A:题目传送门 题目大意:给你N家店,每家店有不同的价格卖苹果,ai元bi斤,那么这家的苹果就是ai/bi元一斤,你要买M斤,问最少花多少元. 题解:贪心,找最小的ai/bi. #in ...
- Codeforces Round #599 (Div. 2)的简单题题解
难题不会啊…… 我感觉写这个的原因就是因为……无聊要给大家翻译题面 A. Maximum Square 简单题意: 有$n$条长为$a_i$,宽为1的木板,现在你可以随便抽几个拼在一起,然后你要从这一 ...
- Educational Codeforces Round 53 (Rated for Div. 2) (前五题题解)
这场比赛没有打,后来补了一下,第五题数位dp好不容易才搞出来(我太菜啊). 比赛传送门:http://codeforces.com/contest/1073 A. Diverse Substring ...
- Codeforces Round #519 by Botan Investments(前五题题解)
开个新号打打codeforces(以前那号玩废了),结果就遇到了这么难一套.touristD题用了map,被卡掉了(其实是对cf的评测机过分自信),G题没过, 700多行代码,码力惊人.关键是这次to ...
- Good Bye 2019(前五题题解)
这套也是后来补得. 我太菜了,第三题就卡着了.想了好久才做出来,要是参加了绝对掉分. D题是人生中做完的第一道交互题,不容易. 比赛传送门 A.Card Game 题目大意:一共有n张互不相同的牌,玩 ...
- Codeforces Round#402(Div.1)掉分记+题解
哎,今天第一次打div1 感觉头脑很不清醒... 看到第一题就蒙了,想了好久,怎么乱dp,倒过来插之类的...突然发现不就是一道sb二分吗.....sb二分看了二十分钟........ 然后第二题看了 ...
- Codeforces Round #609 (Div. 2) A到C题
签到,乘以两个相邻的合数 #include<bits/stdc++.h> using namespace std; int main(int argc, char const *argv[ ...
随机推荐
- H3C 数据链路层
- cp拷贝
1 cp 拷贝.复制 NAME cp - copy files and directories SYNOPSIS cp [OPTION]... [-T] SOURCE DEST -- c ...
- [转]Java Web工程目录结构
说明 介绍java web 工程的基本结构目录.记录java web 工程结构的学习. Java web 结构 java web严格来说分为两类工程结构:一个是工程编译目录结构,一个是工程发布目录结构 ...
- HDU 6623"Minimal Power of Prime"(数学)
传送门 •题意 给你一个大于 1 的正整数 n: 它可以分解成不同的质因子的幂的乘积的形式,问这些质因子的幂中,最小的幂是多少. •题解 定义 $ans$ 表示最终答案: ①如果 $ans \ge 5 ...
- [转]Redis和Memcache区别,优缺点对比
1. Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等. 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供li ...
- nginx+tomcat实现负载均衡(windows环境)
一.准备工作 nginx1.14 nginx1.14下载链接 tomcat8 tomcat8下载链接 windows系统 二.实现目标 访问http://localhost地址时, 将请求轮询到tom ...
- H3C FTP被动数据传输方式
- 列表内容自动向上滚动(原生JS)
效果展示 (鼠标移入,滚动停止:鼠标移出,滚动继续) 实现原理 1. html结构:核心是ul > li,ul外层包裹着div.因为想要内容循环滚动无缝衔接,所以在原有ul后面还要有一个一样内容 ...
- 原生js重写each方法
js原生有个for-each方法,但是只能遍历数组不能遍历对象; jq有个$.each倒是可以遍历数组和对象,但是项目中如果不想用jq呢,我们就用原生来写一个吧. [12,23,34].forEach ...
- nodejs + webpack4 + babel6 结合写Chrome浏览器插件记录(2)
上来先来看下当前实现的效果吧. 前言 首先感谢第一篇留言鼓励的同学,最近各种繁杂的事,时间占用较多,但是也总抽空继续改造这个项目,期间遇到了各种Vue渲染的问题,常规的字符串渲染会在Chrome插件中 ...