感觉自己无可救药了。

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)的更多相关文章

  1. Codeforces Round #651 (Div. 2) A. Maximum GCD(数论)

    题目链接:https://codeforces.com/contest/1370/problem/A 题意 有 $n$ 个数大小分别为 $1$ 到 $n$,找出两个数间最大的 $gcd$ . 题解 若 ...

  2. Codeforces Round #651 (Div. 2) B. GCD Compression(数论)

    题目链接:https://codeforces.com/contest/1370/problem/B 题意 给出 $2n$ 个数,选出 $2n - 2$ 个数,使得它们的 $gcd > 1$ . ...

  3. Codeforces Round #651 (Div. 2) C. Number Game(数论)

    题目链接:https://codeforces.com/contest/1370/problem/C 题意 给出一个正整数 $n$,Ashishgup 和 FastestFinger 依次选择执行以下 ...

  4. Codeforces Round #651 (Div. 2) D. Odd-Even Subsequence(二分)

    题目链接:https://codeforces.com/contest/1370/problem/D 题意 给出一个含有 $n$ 个数的数组 $a$,从中选出 $k$ 个数组成子序列 $s$,使得 $ ...

  5. Codeforces Round #651 (Div. 2) E. Binary Subsequence Rotation(dp)

    题目链接:https://codeforces.com/contest/1370/problem/E 题意 给出两个长为 $n$ 的 $01$ 串 $s$ 和 $t$,每次可以选择 $s$ 的一些下标 ...

  6. 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)是 ...

  7. Codeforces Round #651 (Div. 2) C. Number Game (博弈,数学)

    题意:对于正整数\(n\),每次可以选择使它变为\(n-1\)或者\(n/t\) (\(n\ mod\ t=0\)且\(t\)为奇数),当\(n=1\)时便不可以再取,问先手赢还是后手赢. 题解:首先 ...

  8. Codeforces Round #651 (Div. 2) B. GCD Compression (构造)

    题意:有一个长度为\(2n\)的数组,删去两个元素,用剩下的元素每两两相加构造一个新数组,使得新数组所有元素的\(gcd\ne 1\).输出相加时两个数在原数组的位置. 题解:我们按照新数组所有元素均 ...

  9. Codeforces Round #651 (Div. 2) A. Maximum GCD (思维)

    题意:在\(1\)~\(n\)中找两个不相等的数使得他们的\(gcd\)最大. 题解:水题,如果\(n\)是偶数,那么一定取\(n\)和\(n/2\),\(n\)是奇数的话,取\(n-1\)和\((n ...

随机推荐

  1. Beta冲刺——测试随笔

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 团队作业第五次--Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.测试工作安排 项目 ...

  2. Rocket - util - ECC

    https://mp.weixin.qq.com/s/yato1PrnHe517J8twgZFOg   介绍ECC(Error Correcting Code/Error Checking and C ...

  3. Java实现 LeetCode 224 基本计算器

    224. 基本计算器 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 . 示例 1: 输入: "1 ...

  4. Java实现BFS广度优先查找

    1 问题描述 广度优先查找(Breadth-first Search,BFS)按照一种同心圆的方式,首先访问所有和初始顶点邻接的顶点,然后是离它两条边的所有未访问顶点,以此类推,直到所有与初始顶点同在 ...

  5. Java实现凸包问题

    1 问题描述 给定一个平面上n个点的集合,它的凸包就是包含所有这些点的最小凸多边形,求取满足此条件的所有点. 另外,形象生动的描述: (1)我们可以把这个问题看作如何用长度最短的栅栏把n头熟睡的老虎围 ...

  6. java实现低碳生活大奖赛

    某电视台举办了低碳生活大奖赛.题目的计分规则相当奇怪: 每位选手需要回答 10 个问题(其编号为 1 到 10),越后面越有难度. 答对的,当前分数翻倍:答错了则扣掉与题号相同的分数(选手必须回答问题 ...

  7. java实现取球游戏

    /* 今盒子里有 n 个小球,A.B 两人轮流从盒中取球,每个人都可以看到另一个人取了多少个, 也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出的球的 ...

  8. Java实现计数排序

    1 问题描述 给定一组数据,请使用计数排序,得到这组数据从小到大的排序序列. 2 解决方案 2.1比较计数排序 下面算法的时间复杂度为O(n^2),空间复杂度为O(n).此方法对于任意一组数据均可排序 ...

  9. PAT 换个格式输出整数

    让我们用字母 B 来表示“百”.字母 S 表示“十”,用 12...n 来表示不为零的个位数字 n,换个格式来输出任一个不超过 3 位的正整数.例如 234 应该被输出为BBSSS1234,因为它有 ...

  10. 为.netcore助力--WebApiClient正式发布core版本

    1 前言 WebApiClient已成熟稳定,发布了WebApiClient.JIT和WebApiClient.AOT两个nuget包,累计近10w次下载.我对它的高可扩展性设计相当满意和自豪,但We ...