Good Bye 2019
A. Card Game (CF 1270 A)
题目大意
两个人各持有、张牌,牌序号唯一且在范围~其中。一次操作两个各亮出一张牌,谁牌序号大,谁拿对方的牌,最后没牌者输,问先手是否必赢。
解题思路
很显然谁持有最大牌谁赢......
但是能在一分钟内读完题并敲好代码提交过了真是太强了。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int n,k1,k2; int main(void) { freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int kase; read(kase); for (int i = 1; i <= kase; i++) { //printf("Case #%d: ", i); read(n); read(k1); read(k2); bool qwq=false; for(int u,i=1;i<=k1;++i){ read(u); if (u==n) qwq=true; } for(int u,i=1;i<=k2;++i){ read(u); } if (qwq) printf("YES\n"); else printf("NO\n"); } return 0; }
B. Interesting Subarray (CF 1270 B)
题目大意
给定一个长度为的数组,问是否存在某个区间,有,其中,,,存在则输出并输出任意一个符合要求的区间,否则输出.
解题思路
我们考虑一个符合题目条件的区间,其中最大值和最小值在端点处是最优的选择,不失一般性,我们设最大值在处,最小值在处,则,从中我们可以看出至少有一个,才能有该不等式成立,那也一定有至少一个位置有才行。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int n,u,v; int main(void) { //ios::sync_with_stdio(false); freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int kase; read(kase); for (int i = 1; i <= kase; i++) { //printf("Case #%d: ", i); read(n); read(u); bool qwq=false; int l=0; for(int i=2;i<=n;++i){ read(v); if (ABS(v-u)>1) {qwq=true;l=i-1;} u=v; } if (qwq) printf("YES\n%d %d\n",l,l+1); else printf("NO\n"); } return 0; }
C. Make Good (CF 1270 C)
题目大意
给定个正整数,设个数的和为,异或为,若则这个序列是的,如果不是,最多可增加三个正整数,使得这个序列变成,求添加数的个数以及数的大小。
解题思路
首先一定要是偶数,否则我们先加一个数,然后再考虑和大小。
注意到异或两次同一个数相当于不变,那么如果,那么我们只要再增加两个同样的数,这样不变,而也变成了。
如果,我们再一开始增加一个超大超大的数,让即可,由于,那我们就增加一个的数,即,如果是奇数,就加,然后根据上面的情况即可。
对应代码为注释部分。
这题还有另一种加法,即加两个数和,这样和就变成,异或值变成,这样也符合题意。
还有最优的只用加一个数的方法(如果)
即先后,从低位到高位逐一比较和的每一位是否相等,如果不相等则添一个在该位为的数,添这个数后只会影响和的高位,不会影响低位,然后把这些数加起来就得到我们要的那一个数了。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { //ios::sync_with_stdio(false); freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int kase; read(kase); for (int i = 1; i <= kase; i++) { //printf("Case #%d: ", i); int n; LL sum,xx,u,a; read(n); sum=xx=0; for(int i=1;i<=n;++i){ read(u); sum+=u; xx=xx^u; } printf("2\n%lld %lld\n",xx,xx+sum); //两个数 /* 一个数 xx<<=1; LL ans=0; int id=0; while(sum||xx){ if ((sum^xx)&1){ ans+=(1ll<<id); sum++; xx^=2; } sum>>=1; xx>>=1; ++id; } if (ans) printf("1\n%lld\n",ans); else printf("0\n\n"); */ /* 三个数 if ((xx<<1ll)==sum) printf("0\n\n"); else{ a=(1ll<<50ll); if (sum&1ll) a=a|1ll; sum+=a; xx=(xx^a); xx<<=1; LL qwq=xx-sum; printf("3\n%lld %lld %lld\n",a,(qwq>>1),(qwq>>1)); } */ } return 0; }
D. Strange Device (CF 1270 D)
题目大意
交互题。
给定和,以及一个你并不知道长度为的数俩俩不同的数列和,每次你可以问个互不相同的下标,对方会告诉你这些下标对应的值里,从小到大排列第个小数的位置和值。不能问多于次。最后你的程序要猜出值。
解题思路
一开始妄图想找到个数然后问它们一波得到值结果不可行。然后妄图用并查集维护每个数在的左边还是右边发现数太多了不可控所以我们要考虑少点的数,比如就前个数,每次我们选这其中的个数,相当于把其中的一个数从个数中剔除,然后我们考虑这个剔除的数对第个数的影响。
假设在这个数中,第个数的值为,则如果剔除的一个数小于等于,则第个数会变成另一个数,如果大于,则第个数还是。纵观我们剔除次的结果,可以知道数会出现,而数会出现次,于是我们统计较大的数出现的次数就是答案。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { //ios::sync_with_stdio(false); //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int n,k; read(n); read(k); vector<bool> sign(k+2,false); int ma=0,cnt=0; for(int i=1;i<=k+1;++i){ sign[i]=true; sign[i-1]=false; printf("? "); for(int j=1;j<=k+1;++j) if (!sign[j]) printf("%d ",j); puts(""); fflush(stdout); int u,v; read(u);read(v); if (ma<v){cnt=1;ma=v;}else if (ma==v) ++cnt; } printf("! %d\n",cnt); fflush(stdout); return 0; }
E. Divide Points (CF 1270 E)
题目大意
给出个点坐标,要求将它们分成两个非空集、,使得没有同组的点距离与不同组的点距离相同。
解题思路
由于不大,一开始想着枚举所有距离然后排序,把有相同距离的点对分到同一个组,然后构造了两个反例,一个是所有点分布呈以一个点为圆心的圆上,另一个是两个圆emmmmm。
我们试着根据点的坐标性质进行分类,所有点坐标在的意义下我们可以分成四类:,如果我们对于属于同类的点都放在一个集合里时,它们的、坐标差一定是偶数,这样它们的距离的平方就一定是偶数,这启示我们,如果不同组的点距离的平方是奇数的话,那么就一定没有同组的点距离与不同组的点距离相同。经过分析我们可以知道,点坐标属于或的点与点坐标属于或的点的距离一定是奇数。那么我们就把点坐标属于或放在,点坐标属于或放在即可。再综合一下就是点坐标和是偶数的放在,点坐标和是奇数的放在。
那要是没有点坐标和是奇数或偶数的怎么办?我们先选定一个点为原点进行整体平移,这样就一定有坐标和为偶数的点。如果没有坐标和是奇数点的话,此时所有点坐标和都为偶数,但我们注意到,如果点属于的,它们点的距离的平方是的倍数,而点属于的,它们点的距离的平方除以4会余2,这样我们就把放在,放在即可。若没有的点的话,我们对全部坐标都除以,这样所有点的距离的平方都会除以,但该相等的还是相等,不相等的还是不相等,不影响我们的判断。由于坐标最大不超过,故除以的次数不会超过,重复以上操作即可。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); /* int kase; read(kase); for (int i = 1; i <= kase; i++) { printf("Case #%d: ", i); } */ int n; read(n); vector<int>x,y; for(int u,v,i=0;i<n;++i){ read(u);read(v); x.push_back(u); y.push_back(v); } for(int i=1;i<n;++i){ x[i]-=x[0]; y[i]-=y[0]; } x[0]=y[0]=0; while(1){ vector<int> qwq; for(int i=1;i<n;++i) if ((x[i]+y[i])&1) qwq.push_back(i); if (!qwq.empty()){ printf("%d\n",(int)qwq.size()); for(int i:qwq){ printf("%d ",i+1); } puts(""); return 0; } for(int i=1;i<n;++i) if (x[i]&1) qwq.push_back(i); if (!qwq.empty()){ printf("%d\n",(int)qwq.size()); for(int i:qwq){ printf("%d ",i+1); } puts(""); return 0; } for(int i=1;i<n;++i){ x[i]>>=1; y[i]>>=1; } } return 0; }
G. Subset with Zero Sum (CF 1270 G)
题目大意
给定一个长度为的数组,其中第个元素满足:,请选择一些数使得它们和为,并输出它们的位置。保证有解,若有多解,输出任意一种即可。
解题思路
这题思路清奇......
我们将变形得到。
注意到仍在的范围,我们构造一张有向图,第个点连向第个点。由于每个点都有条出边,那么一定会有一个环,我们考虑环上的点,分别有:
- ......
累加得这样我们就找到了一组符合题目要求的。
(这脑洞是有多大……)
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int kase; read(kase); for (int i = 1; i <= kase; i++) { //printf("Case #%d: ", i); int n; read(n); vector<int> a(n+1); for(int i=1;i<=n;++i) read(a[i]); vector<bool> visit(n+1,false); int qwq=1; while(!visit[qwq]){ visit[qwq]=true; qwq=qwq-a[qwq]; } vector<int> ans; ans.push_back(qwq); int qaq=qwq-a[qwq]; while(qaq!=qwq){ ans.push_back(qaq); qaq=qaq-a[qaq]; } printf("%d\n",(int)ans.size()); for(int i:ans) printf("%d ",i); puts(""); } return 0; }
May 2020 will be the year of high ratings for the hard workers.
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/12121823.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步