CF Round #633 div2 题解
\(Codeforces\) \(Round\) \(633\)
A. Filling Diamonds
\(Description:\)
给定一个数字\(n\),要求你用\(n\)个菱形去填满\(4n-2\)个正三角形,求有多少种不同的填法
其中,这一个菱形由两个正三角形组成,它可以被平移或是旋转,但是不可以被缩放
\(Solution:\)
显然最后这种形状只允许一个竖着的菱形,那么总数就是竖着的菱形所能摆放的位置数
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%d\n",n);
}
return 0;
}
B. Sorted Adjacent Differences
\(Description:\)
给定一个长度为\(n\)的数组\(a\)
你要将其重新排列,使得\(|a_1-a_2|<|a_2-a_3|<···<|a_{n-1}-a_n|\)
输出任意一个满足条件的排列
\(Solution:\)
先排个序,然后从中间开始左右反复横跳的输出即可,这样可以保证\(|a_1-a_2|<|a_2-a_3|<···<|a_{n-1}-a_n|\)成立
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
int t,n,a[100005];
int main(){
int i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(i=n/2,j=n/2+1;i>=1||j<=n;i--,j++){
if(j<=n)printf("%d ",a[j]);
if(i>=1)printf("%d ",a[i]);
}
printf("\n");
}
return 0;
}
C. Powered Addition
\(Description:\)
给定一个数列\(a\),对于每一个数\(a_i\),可以选择一些\(j\),\(j\)不一定连续,将其加上\(\sum2^j\)
使得最后\(a\)成为一个非严格单调递增序列,求调整过程中\(j\)的最大值。
\(Solution:\)
调整过程中\(j\)的最大值就是每次加上的数的二进制的最大位数
对于每一个\(a_i\),显然只需要将其增加至它之前的最大值即可
用\(last\)维护一下这个最大值,统计以下每次加上的数的二进制位数,取最大值输出即可
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
typedef long long lol;
int t,n;
lol a[100005];
int get_bit(lol x){
int ans=0;
while(x){
ans++;
x>>=1;
}
return ans;
}
int main(){
int i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
int ans=0,last=a[1];
for(i=2;i<=n;i++){
if(a[i]>=last){last=a[i];continue;}
ans=max(ans,get_bit(last-a[i]));
}
printf("%d\n",ans);
}
return 0;
}
D. Edge Weight Assignment
\(Description:\)
给定一棵\(n\)个节点的无根树,要求你为每一条边赋一个正整数权值
使得每对叶子节点之间路径的权值的异或和为\(0\)
求最少和最多有多少个不同的权值
权值可以为任何大
\(Solution:\)
由于权值可以任意大
那么就只需要连接在相同节点上的叶子节点到该节点的权值是一样的即可
其他边的权值理论上可以互不相同
一个\(dfs\)搞定
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
int n,a[100005],size,head[100005],in[100005];
bool flag_odd,flag_even;
struct node{
int next,to;
}edge[200005];
void putin(int from,int to){
size++;
edge[size].to=to;
edge[size].next=head[from];
head[from]=size;
}
int dfs(int r,int depth,int fa){
if(in[r]==1){if(depth&1)flag_odd=1;else flag_even=1;return 0;}
int cnt=0,ans=0;
for(int i=head[r];i!=-1;i=edge[i].next){
int j=edge[i].to;
if(j!=fa){
ans+=dfs(j,depth+1,r);
if(in[j]==1)cnt++;
}
}
if(cnt)return ans+cnt-1;
else return ans;
}
int main(){
int i,j,r,ans1,ans2;
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
putin(u,v);
putin(v,u);
in[v]++;in[u]++;
}
for(i=1;i<=n;i++)if(in[i]>1){r=i;break;}
ans2=dfs(r,0,0);
ans2=n-1-ans2;
if(flag_odd&&flag_even)printf("3 ");
else printf("1 ");
cout<<ans2<<endl;
return 0;
}
E. Perfect Triples
\(Description:\)
通过如下方式构造一个数列\(S\)
1.选择一个字典序最小的有序三元组\((a,b,c)\),且满足\(a,b,c\notin S\)且\(a,b,c\)异或和为\(0\)
2.将这个三元组按顺序加入\(S\)
求\(S\)的第\(n\)项