Codeforces Round #633 Div. 2
比赛链接 https://codeforces.com/contest/1339
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197
A. Filling Diamonds(递推)
题意:找填充的找方案数
思路:第 n 层比第 n-1 层多了1(最后一列竖着摆)。递归看,
f
[
n
]
=
f
[
n
−
1
]
+
1
。
f
[
1
]
=
1
f[n]=f[n-1]+1。f[1]=1
f[n]=f[n−1]+1。f[1]=1
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%d\n",n);
}
return 0;
}
B. Sorted Adjacent Differences(绝对值)
思路:排序后,直接从中位数开始交叉放。这样的话,绝对值之差只会越来越大。因为它们距离中位数的距离越来越远
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
ll t,n,a[maxn];
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]);
sort(a+1,a+1+n);
int l,r;
vector<ll> ans;
if(n&1)
l=n/2,r=n/2+2,ans.push_back(a[n/2+1]);
else
l=n/2,r=n/2+1;
while(l>=1)
{
ans.push_back(a[l]);
ans.push_back(a[r]);
l--,r++;
}
for(int i=0;i<=n-1;++i)
cout<<ans[i]<<" ";
}
return 0;
}
C. Powered Addition(二进制)
思路:因为是2进制,而且每一位都可以选择。如果选择了 t 秒,那么后面的任何数,都是可以到达
2
t
2^t
2t 。因此只需要找绝对值之差最大的数 d 。然后填满这个 d 需要的时间
t
t
t ,就是答案。
总结:
- 用2进制可以累积任何数
- 计算 d 需要的时间 t,只需要把它看成是二进制的表示,比如,1011。右移的次数就是位数
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t,n;
ll a[maxn];
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i];
ll maxx=a[1],d=0;
for(int i=2;i<=n;++i)
{
maxx=max(maxx,a[i]);
d=max(d,abs(a[i]-maxx));
}
int cnt=0;
while(d)
{
d>>=1;
cnt++;
}
cout<<cnt<<"\n";
}
return 0;
}
D. Edge Weight Assignment(构造 + DFS)
题意:给定一颗n个节点的树和n-1,任意两个叶节点之间,路径上边权的异或和为0。求最大和最小的不同边权的数量。
思路:
- 最小:如果任意两个叶节点之间的距离为偶数,答案为1;如果存在两点之间的距离为奇数,答案为3
- 最大:最多为n-1,如果存在两个叶节点的距离为2,则答案 -1
实现:
- 所有点到根节点的距离同奇或者同偶,则说明任意两点之间的距离为偶数
- 距离为2的两个叶节点,只需统计入度为1节点的父节点的叶节点数量,即可计算
总结:
- 叶节点:入度为1。邻接表中找叶节点的父节点也简单,就只有唯一一条边相连
- 奇数( ≥ 3 \ge 3 ≥3)个数:至少需要3个数,异或和才为0
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int n;
vector<int> G[maxn];
int in[maxn],depth[maxn],f[maxn];
void dfs(int u,int fa=-1)
{
for(auto v : G[u])
{
if(v==fa)
continue;
depth[v]=depth[u]+1;
dfs(v,u);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n-1;++i)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
in[u]++,in[v]++;
}
for(int i=1;i<=n;++i)
if(in[i]==1)
f[G[i][0]]++;
int ans1=n-1;
for(int i=1;i<=n;++i)
if(f[i]>=2)
ans1-=f[i]-1;
dfs(1);
bool f1=false,f2=false;
for(int i=1;i<=n;++i)
{
if(in[i]==1)
{
if(depth[i]-depth[1]&1)
f1=true;
else
f2=true;
}
}
int ans2=(f1&&f2)?3:1;
printf("%d %d\n",ans2,ans1);
return 0;
}