A.签到,没啥好说
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int a,b,i,total=0,mid;
cin>>a>>b;mid=(a+b)>>1;
if((a+b)&1){
int as=mid-min(a,b);
total=as*(as+1)/2+(as+1)*(as+2)/2;
}
else{
int as=mid-min(a,b);
total=as*(as+1);
}
cout<<total<<endl;
return 0;
}
B.注意到一个有趣的事情,就是每个球队这一轮是否相遇可以通过将球队id+1再除以2来判断;
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int n,a,b,cnt,i,j;
cin>>n>>a>>b;
for(i=0;;i++){
if(!(n>>i))break;
}
cnt=i-1;int cnt1=0;
while(a!=b){
a=(a+1)>>1;b=(b+1)>>1;cnt1++;
}
if(cnt1==cnt)cout<<"Final!"<<endl;
else cout<<cnt1<<endl;
return 0;
}
C.
首先,我们注意到这个数字可选的其实最多就3个。那么如果原来的序列中最大-最小<=1的话,其实是没有得选的,所有数字都会重复。但是如果最大-最小=2的话,那么就有操作空间的。因为要满足总和不变,所有可选操作只有两种:(3个数记为min,min+1,max(其实就是min+2)) 1,把min和max换成两个min+1;
2,把两个min+1换成1个min和一个max 。那么我们考察是(min(min,max))*2比较大还是min+1比较大即可,原代码非常的巧妙;
#include<cstdio>
#include<iostream>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
int main()
{
int n,i,j,k;
map<int,int>cnt;ll total=0;
cin>>n;
for(i=1;i<=n;i++){
scanf("%d",&j);cnt[j]++;
//total+=j;
}
int x=cnt.begin()->first,y;
int a=cnt[x],b=cnt[x+1],c=cnt[x+2];
if(cnt[x]&&cnt[x+2]){
if(2*(y=min(cnt[x],cnt[x+2]))>cnt[x+1]){
cnt[x]-=y;cnt[x+1]+=2*y;cnt[x+2]-=y;
}
else{
cnt[x]+=cnt[x+1]/2;cnt[x+2]+=cnt[x+1]/2;cnt[x+1]%=2;
}
}
cout<<min(a,cnt[x])+min(b,cnt[x+1])+min(c,cnt[x+2])<<endl;
for(i=x;i<x+3;i++)
for(j=1;j<=cnt[i];j++)
cout<<i<<' ';
return 0;
}
D.
题目的关键是发现,其实各个苹果到达根的时间就是他到根的距离,并且,其实我们可以只统计各个苹果到达1的距离即可,因为比如两个苹果同时到达2,而2的下一步是1的话,那么这两个苹果到2和到1的距离必然都是相等的,因此直接统计各个苹果到1的距离,然后%2即可。
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
vector<int>G[100005];
map<int,int>cnt;
void dfs(int x,int fa,int dis)
{
cnt[dis]++;//这个路径长度的果子数++
for(int i=0;i<G[x].size();i++){
if(G[x][i]==fa)continue;
dfs(G[x][i],x,dis+1);
}
}
int main()
{
int n,i,j,k;
cin>>n;
for(i=1;i<n;i++){
scanf("%d",&j);G[j].push_back(i+1);
}
dfs(1,-1,1);
int total=0;
for(auto a=cnt.begin();a!=cnt.end();a++){
total+=a->second%2;
}
cout<<total<<endl;
return 0;
}