Codeforces Round #781 (Div. 2)(ABCD)
Posted 斗奋力努
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #781 (Div. 2)(ABCD)相关的知识,希望对你有一定的参考价值。
Codeforces Round #781 (Div. 2)(ABCD)
A. GCD vs LCM
题意:
给定一个n,将n分成4部分,满足
a
+
b
+
c
+
d
=
n
&
&
g
c
d
(
a
,
b
)
=
=
l
c
m
(
c
,
d
)
a+b+c+d=n\\&\\&gcd(a,b)==lcm(c,d)
a+b+c+d=n&&gcd(a,b)==lcm(c,d)
思路:
先判断n是否为4的倍数,是的话分成4等份,
a
=
b
=
c
=
d
a=b=c=d
a=b=c=d
不是的话,保证
c
=
d
=
1
c=d=1
c=d=1,那么
l
c
m
(
c
,
d
)
=
1
lcm(c,d)=1
lcm(c,d)=1,剩下保证gcd为1就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,a,b,c,d;
void solve()
scanf("%d",&n);
if(n%4==0)printf("%d %d %d %d\\n",n/4,n/4,n/4,n/4);return;
c=d=1; n-=2;
if(n%2==1) a=n/2,b=(n+1)/2;
else a=n/2-1,b=n/2+1;
printf("%d %d %d %d\\n",a,b,c,d);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
B. Array Cloning Technique
题意:
给定长度为n的序列,最少进行多少次操作是使得有一个序列的元素全部相等。
一次操作:
①复制任意一个序列
②交换任意两个序列中的一个元素
思路:
肯定是去使初始最多的元素全部填满某个序列,如果总数不够,就去复制一次。
然后将复制出来的全部移到原序列。还不够就再复制,然后再交换,直到填满为止
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m,q;
map<int,int>mp;
void solve()
mp.clear();
scanf("%d",&n);
int mx=0;
for(int i=1;i<=n;i++)
int x;scanf("%d",&x);
mp[x]++; mx=max(mx,mp[x]);
int ans=0;
while(mx<n)
ans++;
ans+=min(mx,n-mx);
mx*=2;
printf("%d\\n",ans);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
C. Tree Infection
题意:
一棵树。每秒钟每个有儿子节点感染的节点i,可以感染节点i的一个其他健康儿子节点,同时可以指定一个健康节点感染。问最少多少时间,全部节点感染?
思路:
很容易想到,节点之间有关系只能是同属于一个节点的儿子,只有这样a感染了才能去感染b,不然b就只能指定感染,耗费时间。
那么我们可以将全部节点分成一些集合,划分条件为同一个节点的儿子节点。
然后秉承
“
难
事
”
先
做
,
“
易
事
”
后
做
“难事”先做,“易事”后做
“难事”先做,“易事”后做的原则,我们初始一次在指定感染的时候,按照集从大到小的顺序感染,这样每感染后一个节点时,我们可以之前的可以传递感染,这样在每个集合都有感染后,原来大集合已经感染的也最多,这样是最优的。
剩下的同样在这张规则下,继续指定感染。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,p[N],t1,t2;
vector<int>edge[N],num;
void solve()
t1=t2=0; num.clear();
scanf("%d",&n);
edge[0].push_back(1);
for(int i=2;i<=n;i++)
int x; scanf("%d",&x);
edge[x].push_back(i);
for(int i=0;i<=n;i++)
int len=edge[i].size();
if(len!=0) num.push_back(len);
sort(num.begin(),num.end());
t1=num.size();
priority_queue<int>q;
for(int i=0;i<t1;i++) q.push(num[i]-(i+1));
while(1)
if(q.empty()) break;
auto u=q.top(); q.pop();
if(u<=0) continue;
if(u<=t2) break;
q.push(u-1); //指定感染
t2++;
printf("%d\\n",t1+t2);
for(int i=0;i<=n;i++) edge[i].clear();
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
D. GCD Guess
题意:
每个询问a,b ,得到输出gcd(a+x,b+x) ,最多询问30次,问x的值是多少,x的范围(1<=x<=1e9)
思路:
这题挺好想的吧,1e9正好只有30位,所以我们一位位去判断是否可行就好了。
我们判断第i为的0/1情况时,我们是得到
a
+
x
=
(
1
<
<
i
)
a+x=(1<<i)
a+x=(1<<i),同时
b
+
x
b+x
b+x的第i位也是1,但是要比(1<<i)大。
这样如果
g
c
d
!
=
(
1
<
<
i
)
gcd!=(1<<i)
gcd!=(1<<i),那么第i位取1。因为如果第i位为1的话,再加(1<<i),会使得第i位为0,这样gcd就肯定不会为(1<<i)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int query(int a,int b)
cout<<"? "<<a<<" "<<b<<endl;
int gd;
cin>>gd;
return gd;
void print(int x)
cout<<"! "<<x<<endl;
void solve()
int ans=0;
for(int bit=0;bit<30;bit++) //判断bit位
int ned1=(1<<bit);
int ned2=(1<<bit)+(1<<30);
int gd=query(ned1-ans,ned2-ans); //将[0,max(0,bit-1)]位的值减去
if(gd!=ned1) ans+=ned1;
print(ans);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
以上是关于Codeforces Round #781 (Div. 2)(ABCD)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #781 (Div. 2)(ABCDE)
Codeforces Round #436 E. Fire(背包dp+输出路径)
[ACM]Codeforces Round #534 (Div. 2)
Codeforces 781C Underground Lab 构造