Codeforces Round #618 (Div. 2)
A. Non-zero
题意
输入n个数,每次可以选定其中的一段数将其所有数+1,该操作可以执行若干次,求至少需要几次将所有数之和跟积都不为0
题解
先满足积不为0,直接统计出原本的0的个数,将其全部+1,然后再判断和是否为0,为0则任选一个数+1
代码
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{ long N,i,sum,num,n,x;
scanf("%ld",&N);
while(N--){
sum=num=0;
scanf("%ld",&n);
for(i=1;i<=n;i++){
scanf("%ld",&x);
sum+=x;
if(!x)
num++;
}
printf("%ld\n",num+((num+sum==0)?1:0));
}
return 0;
}
B. Assigning to Classes
题意
将2n个数分配到2个数列里,求这两个数列的中位数差值最小为多少
题解
直接对所有数进行排序,奇数下标的分到第一个数列,偶数下标的分到另一个数列,所以最小中位数差值为n+1下标和n下标数之差
代码
#include<cstdio>
#include<algorithm>
#define def 200010
using namespace std;
long a[def];
int main()
{ long N,n,i;
scanf("%ld",&N);
while(N--){
scanf("%ld",&n);
for(i=1;i<=2*n;i++)
scanf("%ld",&a[i]);
sort(a+1,a+2*n+1);
printf("%ld\n",a[n+1]-a[n]);
}
return 0;
}
C. Anu Has a Function
题意
定义一个函数 f ( x , y ) = ( x ∣ y ) − y f(x,y)=(x|y)-y f(x,y)=(x∣y)−y。给定n个数,求能使 f ( f ( . . . f ( f ( a 1 , a 2 ) , a 3 ) . . . ) , a n ) f(f(...f(f(a_1,a_2),a_3)...),a_n) f(f(...f(f(a1,a2),a3)...),an)最小的排列
题解
由于
(
x
∣
y
)
−
y
=
x
−
(
x
&
y
)
(x|y)-y=x-(x\&y)
(x∣y)−y=x−(x&y)
相当于二进制下x去掉与y相同的部分,所以,
f
(
f
(
.
.
.
f
(
f
(
a
1
,
a
2
)
,
a
3
)
,
.
.
.
)
,
a
n
)
=
a
1
−
(
a
1
&
(
a
2
∣
a
3
∣
.
.
.
∣
a
n
)
)
f(f(...f(f(a_1,a_2),a_3),...),a_n)=a_1-(a_1\&(a_2|a_3|...|a_n))
f(f(...f(f(a1,a2),a3),...),an)=a1−(a1&(a2∣a3∣...∣an)),即对于第一个数的所有有1的位置,如果他是“独一无二”的,那就能够保留下来,而保留下来的就是
f
(
.
.
.
)
f(...)
f(...)的结果
比如,
对于第一个数101110,所有的1为100000、1000、100和10,根据统计结果,独一无二的有100000和100,所以结果就是100100
第二个数001010的结果是000000
第三个数010011的结果是010001
比较结果可知,第一个数101110的结果是最大的
同时根据上面的式子,可以推断 f ( . . . ) f(...) f(...)的结果只与第一个数有关,与后面的数的排列无关,所以只用确定第一个数就好了
代码
#include<cstdio>
#include<algorithm>
#define def 100010
using namespace std;
long a[def],num[100];
int main()
{ long n,i,j,ans_q,maxx,q;
scanf("%ld",&n);
for(i=1;i<=n;i++){
scanf("%ld",&a[i]);
for(j=0;(1<<j)<=a[i];j++)
if(a[i]&(1<<j))
num[j]++;
}
ans_q=0;
maxx=1;
for(i=1;i<=n;i++){
q=0;
for(j=0;(1<<j)<=a[i];j++)
if(num[j]==1&&(a[i]&(1<<j)))
q|=1<<j;
if(q>ans_q){
maxx=i;
ans_q=q;
}
}
printf("%ld ",a[maxx]);
for(i=1;i<=n;i++)
if(maxx!=i)
printf("%ld ",a[i]);
printf("\n");
return 0;
}
D. Aerodynamic
题意
给定一个凸多边形,将其所有顶点轮流移到原点,求移动轨迹的最外框形成的多边形与原多边形是否相似
题解
在移动的过程中,一个角的角度决定了最后形成的多边形的对角的角度,所以要使最后形成的图形与原来的相似,原图形就必须是中心对称图形,一遍循环判断即可
代码
#include<cstdio>
#include<set>
#define abs(i) (((i)>0)?(i):-(i))
#define def 100010
using namespace std;
struct node{
double x,y;
node(double x=0,double y=0){
this->x=x;
this->y=y;
}
friend bool operator <(node a,node b){
if(a.x!=b.x)
return a.x<b.x;
else
return a.y<b.y;
}
}a[def],sum;
set<node>st;
int main()
{ long n,i;
scanf("%ld",&n);
for(i=1;i<=n;i++){
scanf("%lf%lf",&a[i].x,&a[i].y);
sum.x+=a[i].x;
sum.y+=a[i].y;
}
sum.x/=n;
sum.y/=n;
for(i=1;i<=n;i++){
auto now=st.find(node(-(a[i].x-sum.x),-(a[i].y-sum.y)));
if(now==st.end())
st.insert(node((a[i].x-sum.x),(a[i].y-sum.y)));
else
st.erase(now);
}
if(st.empty())
printf("YES\n");
else
printf("NO\n");
return 0;
}