Codeforces Round #580 (Div. 2)
Posted acmerszl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #580 (Div. 2)相关的知识,希望对你有一定的参考价值。
Solutions
A. Choose Two Numbers
题意:
给出\(A,B\)两个集合,\(A,B\) 集合分别选一个数\(a,b\) ,使得\(a+b\notin\ A,B\)
思路:
每个集合选出最大值,必定满足条件。emmmmm比赛的时候傻了。
//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
const int N=100010;
const int inf=0X3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int mod = 1000000007;
typedef long long ll;
int a[110];
int main()
#ifdef DEBUG
freopen("in.txt","r",stdin);
#endif
int n,m,ans1,ans2;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ans1=*max_element(a+1,a+n+1);
scanf("%d",&m);
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
ans2=*max_element(a+1,a+m+1);
printf("%d %d\n",ans1,ans2);
B. Make Product Equal One
题意:
给出\(a_1,a_2,\dots,a_n\),可以进行任意次操作:选择其中任意一个数\(+1,-1\),使得最后\(a_1\asta_2\ast\dots\asta_n=1\)。
思路:
负数就变为\(-1\),整数就变为\(1\),但是若负数个数为奇数,则需要有一个变为\(1\),但是存在\(0\)的话,则不需要。
//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
const int N=100010;
const int inf=0X3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int mod = 1000000007;
typedef long long ll;
int main()
#ifdef DEBUG
freopen("in.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
ll ans=0,ok=0,res=1;
for(int i=1;i<=n;i++)
int x;
scanf("%d",&x);
if(x>=1) ans+=x-1;
else if(x<0) ans+=-1-x,res*=-1;
else if(!x) ans+=1,ok=1;
if(ok||res==1) printf("%lld\n",ans);
else printf("%lld\n",ans+2);
C. Almost Equal
题意:
给出数字\(n\),你需要安排的数为\(1\sim2n\),组成一个环。每连续\(n\)个数求一次和\(sum_i\),输出一个合法的序列,使得\(\foralli,j,\ \midsum_i-sum_j\mid\leq1\)
思路:
比赛时我构造出序列,然后队友写出\(check\) 代码,构造时发现分为两部分,右边最上面写一个最大的,左边最下面写次大的,然后左边再写次次大的,右边再写次次次大的,交替进行。可以理解为右边为先手,然后左边变为先手。构造完以后,用数组模拟成环,然后前缀和搞一搞模拟\(check\) 即可。
正解:
我们定义\(s_i=a_i+a_i+1+a_i+2+\dots+a_i+n-1\),
\(S_i+1-S_i=\left(a_i+1+a_i+2+a_i+3+\cdots+a_i+n\right)-\left(a_i+a_i+1+a_i+2+\cdots+a_i+n-1\right)=a_i+n-a_i\) 根据题意有\(\mida_i+n-a_i\mid\leq1\),因为\(a\)数组都是不同的,所以\(\mida_i+n-a_i\mid=1\)
则根据题意有:\(a_i+n-a_i,a_i+n+1-a_i+1\) 有相反的符号。 证:若他们都等于\(1\),则\(S_i+2-S_i=(S_i+2-S_i+1)+(S_i+1-S_i)=(a_i+n+1-a_i+1)+(a_i+n-a_i)=2\),若都为\(-1\)也一样。因此,对于\(a_i+n-a_i\),他们是交替的\(1,-1,1,\dots\)。
- 如果\(n\)为偶数,存在矛盾\(a_i+n-a_i=-(a_(i+n)+n-a_i+n)\),但是由于交替,所以他们应该是相等的
- 如果\(n\)为奇数,\(i:1\simn\)
- 若\(i\)为奇数,\(a_i=2i,a_i+n=2i-1\)
- 若\(i\)为偶数,\(a_i=2i-1,a_i+n=2i\)
//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
const int N=100010;
const int inf=0X3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int mod = 1000000007;
typedef long long ll;
int a[N],b[N],c[4*N];
ll ans[4*N];
int main()
#ifdef DEBUG
freopen("in.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
bool flag=true;
int cura=0,curb=0;
int x=2*n;
while(x)
if(flag)
b[++curb]=x--;
a[++cura]=x--;
else
a[++cura]=x--;
b[++curb]=x--;
flag=!flag;
int cur=0;
for(int i=cura;i>=1;i--) c[++cur]=a[i];
for(int i=curb;i>=1;i--) c[++cur]=b[i];
int len=cur;
for(int i=1;i<=len;i++) c[++cur]=c[i];
//for(int i=1;i<=cur;i++) printf("%d\n",c[i]);
set<ll> s;
for(int i=1;i<=n;i++)ans[i]=ans[i-1]+c[i];
s.insert(ans[n]);
for(int i=n+1;i<=3*n;i++)
ans[i]=ans[i-1]-c[i-n]+c[i];
s.insert(ans[i]);
if(s.size()>2)puts("NO");
else if(s.size()==2)
set<ll>::iterator it=s.begin();
ll s1,s2;
s1=*it;
it++;
s2=*it;
if(abs(s1-s2)!=1)puts("NO");
else
puts("YES");
for(int i=1;i<=2*n;i++)printf("%d%c",c[i],i==2*n?'\n':' ');
else
puts("YES");
for(int i=1;i<=2*n;i++)printf("%d%c",c[i],i==2*n?'\n':' ');
//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
const int N=100010;
const int inf=0X3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int mod = 1000000007;
typedef long long ll;
int a[2*N];
int main()
#ifdef DEBUG
freopen("in.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
if(n%2==0) puts("NO");return 0;
puts("YES");
for(int i=1;i<=n;i++)
if(i&1) a[i]=2*i,a[i+n]=2*i-1;
else a[i]=2*i-1,a[i+n]=2*i;
for(int i=1;i<=2*n;i++) printf("%d%c",a[i],i==2*n?'\n':' ');
D. Shortest Cycle
题意:
给出\(a_1,a_2,\dots,a_n\),当作图中的\(n\)个点,对于\(\foralli,j(i\neqj),a_i\&a_j\neq0\),\(a_i\)和\(a_j\)连一条边,然后求最小环。
思路:
比赛时队友考虑二进制,都把\(60\)个位置画出来了。我也准备好\(floyd\)最小环了。但是沙雕了,感觉每个位置都连边,复杂度太大emmmmmm。其实二进制对应位置\(1\)的个数大于\(2\),那么最小环就是\(3\),然后最多\(120\)个点\(60\)条边(可能不确切),然后\(floyd\)跑最小环即可。
\(floyd\)求最小环:\(d[i][j]\)为\(i\)到\(j\)不包含\(k\)点的最短距离。所以对于当前\(k\),我们已经求得\(1\simk-1\)的\(d[i][j]\),然后枚举\(1\simk-1\)的\(d[i][j]\),然后更新答案,\(ans=min(ans,a[i][k]+a[k][j]+d[i][j])\),表示包含\(k\)的环,其中\(a\)数组为最初距离。
//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
const int inf=0X3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int mod = 1000000007;
typedef long long ll;
int ans=60;
ll b[N],a[150][150],d[150][150];
int tot;
int main()
#ifdef DEBUG
freopen("in.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
ll x;
for(int i=1;i<=n;i++)
scanf("%lld",&x);
if(x) b[++tot]=x;
for(int i=0;i<=60;i++)
int cnt=0;
for(int j=1;j<=tot;j++)
if(b[j]&(1ll<<i)) ++cnt;
if(cnt>=3) puts("3");return 0;
for(int i=1;i<=tot;i++)
for(int j=1;j<=tot;j++)
if(i==j) d[i][j]=a[i][j]=0;
else d[i][j]=a[i][j]=inf;
for(int i=1;i<=tot;i++)
for(int j=1;j<=tot;j++)
if(i==j) continue;
if(b[i]&b[j]) a[i][j]=d[i][j]=1;
//memcpy(d,a,sizeof(a));
for(int k=1;k<=tot;k++)
for(int i=1;i<=k-1;i++)
for(int j=1;j<=k-1;j++)
if(i!=j&&a[i][k]+a[k][j]+d[i][j]<ans)
ans=a[i][k]+a[k][j]+d[i][j];
for(int i=1;i<=tot;i++)
for(int j=1;j<=tot;j++)
if(d[i][j]>d[i][k]+d[k][j])
d[i][j]=d[i][k]+d[k][j];
if(ans==60) puts("-1");
else printf("%d\n",ans);
以上是关于Codeforces Round #580 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
C. Almost Equal ( Codeforces Round #580 (Div. 2) )
Codeforces Round #580 (Div. 2)
Codeforces Round #580 (Div. 2)
Codeforces Round #580 (Div. 2)赛后总结