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 ...
随机推荐
- 多服务器 vps 管理方法,十款远程桌面软件测评分析
作为运维工作者,从几年前巨大的工作量到如今有了极大的改善,这些年试用的远程桌面管理软件不在少数. 远程桌面是微软公司为了方便网络管理员管理维护服务器而推出的一项服务.从windows 2000 ser ...
- seo网站优化收录过少的病因分析-智狐seo顾问
seo网站优化收录过少的病因分析 很多网站优化人员都了解,一个网站收录的重要性,企业网站要想可以在百度中占据一个良好的排名,获取的权重更高,那么网站收录自然就上去了,很多站长们在操作的过程中就会出现不 ...
- Alpha冲刺——4.30
这个作业属于哪个课程 软件工程 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 Alpha冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.规 ...
- Rocket - util - Broadcaster
https://mp.weixin.qq.com/s/ohBVNAXZUA538qSxfBGMKA 简单介绍Broadcaster的实现. 1. Broadcaster 广播即是 ...
- Rocket - diplomacy - LazyModuleImpLike
https://mp.weixin.qq.com/s/gDbUto1qd7uWbpnxovr5pg 介绍LazyModuleImpLike类的实现. 1. wrapper LazyMo ...
- Chisel3 - Tutorial - Stack
https://mp.weixin.qq.com/s/-AVJD1IfvNIJhmZM40DemA 实现后入先出(last in, first out)的栈. 参考链接: https://gi ...
- Dubbo源码笔记-服务注册
今天来简单做一下Dubbo服务注册部分源码学习手记. 一.Dubbo配置解析 目前Dubbo最多的用法就是跟Spring集成,既然跟Spring集成,那么,Dubbo对象的实例化都将交由Spring统 ...
- Java实现 LeetCode 632 最小区间(又是先序队列,官方给的是堆)
632. 最小区间 你有 k 个升序排列的整数数组.找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中. 我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a ...
- Java实现 LeetCode 537 复数乘法(关于数学唯一的水题)
537. 复数乘法 给定两个表示复数的字符串. 返回表示它们乘积的字符串.注意,根据定义 i2 = -1 . 示例 1: 输入: "1+1i", "1+1i" ...
- Java实现 LeetCode 313 超级丑数
313. 超级丑数 编写一段程序来查找第 n 个超级丑数. 超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数. 示例: 输入: n = 12, primes = [2,7, ...