Codeforces Round #651 (Div. 2)
感觉自己无可救药了。
A题:找到小于等于n的两个不同的数的gcd最大是多少,显然是floort(n/2)。设这两数是a * gcd, b * gcd然后gcd(a,b) = 1,那么gcd要尽量大,不妨就a = 1,b = 2。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std; typedef long long ll;
typedef pair<int,int> pi; using namespace std;
int t;
int main() {
cin >> t;
while (t--) {
int n;
cin >> n;
n = n / ;
cout << n << endl;
}
}
B题:给定2n个数,从中去掉两个数。剩下的数配成n - 1对,然后要求这些对的和的最大gcd大于1。大于1,那就gcd等于2就好了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std; typedef long long ll;
typedef pair<int,int> pi; const int N = ; int n, cnt[], t;
struct node{
int val, i;
}a[N*]; bool cmp(node x,node y) {
return (x.val & ) < (y.val & );
}
void solve() {
scanf("%d", &n);
cnt[] = cnt[] = ;
rep(i,, n * ) scanf("%d", &a[i].val), a[i].i = i,cnt[a[i].val & ]++;
sort(a + , a + n * + , cmp);
if (cnt[] & ) {
for(int i = ; i < n * ; i+=) {
printf("%d %d\n", a[i].i, a[i+].i);
}
return;
}
for(int i = ; i < n * - ; i+=) {
printf("%d %d\n", a[i].i, a[i+].i); }
return ;
} int main() {
scanf("%d", &t);
while(t--) {
solve();
}
}
C题:game题,给一个数n,每次可以减1,如果有奇数因子可以除以奇数因子(包括本身),轮流操作,到1就输了。不知道有什么好做法,写了一堆if。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std; typedef long long ll;
typedef pair<int,int> pi; const int N = ; int dp[N];
bool isprime(int x) {
for(int i = ; i * i <= x; i++) {
if (x % i == ) return ;
}
return ;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
if (n == ) {
printf("FastestFinger\n");
}
else if (n == ) {
puts("Ashishgup");
}
else if (n & ) {
puts("Ashishgup");
}
else{
int cnt = ;
while (n % ==) cnt++, n /= ;
if (n == ) {
puts("FastestFinger");
}
else if (cnt == ) {
if (isprime(n)) puts("FastestFinger");
else puts("Ashishgup");
}
else puts("Ashishgup");
}
}
}
D题:从一个数组里找一个长度为k的子序列,子序列的代价是,子序列的奇数位和偶数位中的最大值中的较小的值。猜测二分贪心是个好做法,然后过了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std; typedef long long ll;
typedef pair<int,int> pi; const int N = ; int n, k;
int a[N]; bool solve(int x) {
int f = ;
int cnt = ;
rep(i,,n) {
if (cnt % == ) cnt++;
else if (a[i] <= x) cnt++;
}
if (cnt >= k) return ;
cnt = ;
rep(i,,n) {
if (cnt & ) cnt++;
else if(a[i] <= x) cnt++;
}
if (cnt >= k) return ;
return ;
} int main() {
scanf("%d %d", &n, &k);
rep(i,,n) scanf("%d", &a[i]);
int l = , r = 1e9;
while (l < r) {
//cerr << l << " " << r << endl;
int mid = (l + r) >> ;
if (solve(mid)) r = mid;
else l = mid + ;
}
printf("%d\n", l);
}
E题:给你两个长度相等的01串,每次可以选择第一个串中的一个子序列,对子序列进行循环右移(不太会简单描述这个操作),然后问最少多少次可以让两个串一样,或者无法实现。
如果两个串01数量不想等就不行,否则就可以。而且我们直接忽视掉已经匹配的位置。然后第一个串就是一堆01,现在要让0到1的位置,1到0的位置。最直接的方法直接配对然后全部循环右移即可。
01可以一次变10。发现010101可以一次变101010也就是说交替的01一次做能减少我们的操作次数。然后就找一下每个0能不能找到交替的1。然后就瞎写了写就莫名其妙过了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std; typedef long long ll;
typedef pair<int,int> pi; const int N = 1e6 + ;
int n;
char s[N], t[N];
int a[N];
int tot;
int ans;
//int lens, lent
int cnts, cntt;
int main() {
scanf("%d", &n);
scanf("%s", s + );
scanf("%s", t + );
rep(i,,n) if (s[i] == '') cnts++;
rep(i,,n) if (t[i] == '') cntt++;
if (cnts != cntt) {
puts("-1");
return ;
}
// int tot = 0;
rep(i,,n) {
if (s[i] == t[i]) continue;
a[++tot] = s[i] - '';
}
ans = tot;
//cerr << tot << "!!!" << endl;
//rep(i,1,tot) cerr << a[i] << " "; cerr << endl;
int j = ;
rep(i,,tot) {
if (a[i] != ) continue;
j = max(i, j);
while (a[j] == && j <= tot) j++;
if (j <= tot) {
ans--;
j++;
}
}
j = tot;
dow(i,tot,) {
if (a[i] != ) continue;
j = min(i, j);
while (a[j] == && j >= ) j--;
if (j >= ) {
ans --;
j--;
}
}
printf("%d\n", ans);
}
f:一个树上,有两个hidden的点。每次询问一个点集,返回到两点距离之和最小的一个点和到两点的距离之和。11次之内搞出来。1000个点
并不会做。然后就等第二天看题解了。
询问所有点,找出两点间路径上的一个点,然后二分,询问深度为mid的所有点,如果说返回的距离大于第一次询问的点,深度就过深了,然后10次内就能搞出某个hidden的点,然后就知道另一个点的深度再询问一次就好。
如果两点距离为d,那么至少有一个点深度是ceil(d / 2),那么就相当于使二分的边界少了一半,11次就能搞定。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std; typedef long long ll;
typedef pair<int,int> pi; const int N = ; struct edge{
int to,next;
}e[N << ];
int n, cnt, h[N];
int dep[N];
int rt, d;
pi ans[N];
int vis[N];
void add(int u,int v) {
e[++cnt] = (edge) {v, h[u]}; h[u] = cnt;
} void dfs(int x) {
for (int i = h[x]; i; i = e[i].next) {
int v = e[i].to;
if (!dep[v] && v != rt) dep[v] = dep[x] + , dfs(v);
}
}
void dfs2(int x, vector<int> &cnt, int dis) {
vis[x] = ;
if(dis == d) {
cnt.push_back(x);
return ;
}
for (int i = h[x]; i; i = e[i].next) {
int v = e[i].to;
if (!vis[v]) dfs2(v, cnt, dis + );
}
}
void solve() {
cnt = ;
int x, y;
int a = , b = ;
memset(h, , sizeof(h));
memset(dep, , sizeof(dep));
memset(ans, , sizeof(ans));
scanf("%d", &n);
rep(i,,n-) {
int u, v;
scanf("%d %d", &u, &v);
add(u, v); add(v, u);
}
printf("? %d ", n);
rep(i,,n) printf("%d ", i); puts("");
fflush(stdout);
scanf("%d %d", &rt, &d);
int l = (d + ) / , r = d;
dfs(rt);
ans[] = make_pair(rt, d);
while() {
int mid = (l + r + ) >> ;
if (!ans[mid].fi) {
vector<int> temp;
rep(i,,n) if (dep[i] == mid) temp.push_back(i);
int cnt = temp.size();
if (cnt == ) {
r = mid - ;
continue;
}
printf("? %d ", cnt);
rep(i,,cnt-) printf("%d ", temp[i]); puts("");
fflush(stdout);
scanf("%d %d", &x, &y);
ans[mid] = make_pair(x, y);
} if (ans[mid].se > d) r = mid - ;
else l = mid;
if (l == r && l == mid) {a = ans[l].fi; break;}
} vector<int> temp;
memset(vis, , sizeof(vis));
dfs2(a, temp, );
int cnt = temp.size();
if (cnt == ) b = temp[];
else {
printf("? %d ", cnt);
rep(i,, cnt - ) printf("%d ", temp[i]); puts("");
fflush(stdout);
scanf("%d %d", &x, &y);
b = x;
}
printf("! %d %d\n", a, b);
string s;
fflush(stdout);
cin >> s;
} int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
}
感觉自己明明d、e都不会做就是瞎蒙对的……
然后交互题尽量应该把交互的过程封装一下。
Codeforces Round #651 (Div. 2)的更多相关文章
- Codeforces Round #651 (Div. 2) A. Maximum GCD(数论)
题目链接:https://codeforces.com/contest/1370/problem/A 题意 有 $n$ 个数大小分别为 $1$ 到 $n$,找出两个数间最大的 $gcd$ . 题解 若 ...
- Codeforces Round #651 (Div. 2) B. GCD Compression(数论)
题目链接:https://codeforces.com/contest/1370/problem/B 题意 给出 $2n$ 个数,选出 $2n - 2$ 个数,使得它们的 $gcd > 1$ . ...
- Codeforces Round #651 (Div. 2) C. Number Game(数论)
题目链接:https://codeforces.com/contest/1370/problem/C 题意 给出一个正整数 $n$,Ashishgup 和 FastestFinger 依次选择执行以下 ...
- Codeforces Round #651 (Div. 2) D. Odd-Even Subsequence(二分)
题目链接:https://codeforces.com/contest/1370/problem/D 题意 给出一个含有 $n$ 个数的数组 $a$,从中选出 $k$ 个数组成子序列 $s$,使得 $ ...
- Codeforces Round #651 (Div. 2) E. Binary Subsequence Rotation(dp)
题目链接:https://codeforces.com/contest/1370/problem/E 题意 给出两个长为 $n$ 的 $01$ 串 $s$ 和 $t$,每次可以选择 $s$ 的一些下标 ...
- Codeforces Round #651 (Div. 2) A Maximum GCD、B GCD Compression、C Number Game、D Odd-Even Subsequence
A. Maximum GCD 题意: t组输入,然后输入一个n,让你在区间[1,n]之间找出来两个不相等的数a,b.求出来gcd(a,b)(也就是a,b最大公约数).让你求出来最大的gcd(a,b)是 ...
- Codeforces Round #651 (Div. 2) C. Number Game (博弈,数学)
题意:对于正整数\(n\),每次可以选择使它变为\(n-1\)或者\(n/t\) (\(n\ mod\ t=0\)且\(t\)为奇数),当\(n=1\)时便不可以再取,问先手赢还是后手赢. 题解:首先 ...
- Codeforces Round #651 (Div. 2) B. GCD Compression (构造)
题意:有一个长度为\(2n\)的数组,删去两个元素,用剩下的元素每两两相加构造一个新数组,使得新数组所有元素的\(gcd\ne 1\).输出相加时两个数在原数组的位置. 题解:我们按照新数组所有元素均 ...
- Codeforces Round #651 (Div. 2) A. Maximum GCD (思维)
题意:在\(1\)~\(n\)中找两个不相等的数使得他们的\(gcd\)最大. 题解:水题,如果\(n\)是偶数,那么一定取\(n\)和\(n/2\),\(n\)是奇数的话,取\(n-1\)和\((n ...
随机推荐
- 团队作业第五次——Alpha冲刺
这个作业属于哪个课程 软件工程 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 Alpha冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.代码规范与计划 ...
- Rocket - jtag - JtagTap
https://mp.weixin.qq.com/s/0u9jM2u-FkTlrk3QNuZaBw 简单介绍JtagTap的实现. 1. 简单介绍 定义TAP(Test Access Port)所需要 ...
- Java实现 LeetCode 754 到达终点数字(暴力+反向)
754. 到达终点数字 在一根无限长的数轴上,你站在0的位置.终点在target的位置. 每次你可以选择向左或向右移动.第 n 次移动(从 1 开始),可以走 n 步. 返回到达终点需要的最小移动次数 ...
- Java实现蓝桥杯历届试题区间移位
问题描述 数轴上有n个闭区间D1,-,Dn.其中区间Di用一对整数[ai, bi]来描述,满足ai < bi.已知这些区间的长度之和至少有10000.所以,通过适当的移动这些区间,你总可以使得他 ...
- 【原创】Linux中断子系统(二)-通用框架处理
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- js数组的常见操作( push、pop、unshift、shift、splice、concat、 join)的用法
1.数组添加删除 头部或尾部( push().pop().unshift().shift() ) 例2.数组尾部添加 push()方法可向数组的末尾添加一个或多个元素,并返回新的长度 语法:array ...
- Spring:工厂模式哪里解耦了?
菜瓜:我一定是太菜了,为什么别人说Spring屏蔽了new关键字创建对象就很丝滑?我完全get不到这个操作的好处啊,我自己写new它也很香啊 水稻:emmmm,换个角度想啊,如果把现在用的注解@Aut ...
- @atcoder - AGC026F@ Manju Game
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个含 N 个数的序列,Alice 与 Bob 在博弈.Al ...
- vue-toy: 200行代码模拟Vue实现
vue-toy 200行左右代码模拟vue实现,视图渲染部分使用React来代替Snabbdom,欢迎Star. 项目地址:https://github.com/bplok20010/vue-toy ...
- Vugen使用技巧
调整各种选项的超时时间