Codeforces Round #772 (Div. 2)(ABCDE)
Posted 斗奋力努
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #772 (Div. 2)(ABCDE)相关的知识,希望对你有一定的参考价值。
Codeforces Round #772 (Div. 2)(ABCDE)
A. Min Or Sum
题意:给一个长度为n的序列,可以多次进行操作,每次选择不同的i,j,使得满足
a
[
i
]
∣
a
[
j
]
=
x
∣
y
a[i]|a[j]=x|y
a[i]∣a[j]=x∣y,x、y任意,问最后序列的最小总和。
思路:因为可以一直或操作,
a
[
i
]
∣
a
[
j
]
=
x
∣
y
a[i]|a[j]=x|y
a[i]∣a[j]=x∣y也可以看成为变化后
a
[
i
]
+
a
[
j
]
a[i]+a[j]
a[i]+a[j]的值。所以我们只要看所有数在二进制下的哪些位是1就行了,最后加起来就是答案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=105;
ll n,sum,bit[35];
void solve()
sum=0;
for(ll i=0;i<=30;i++) bit[i]=0;
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
ll x;scanf("%lld",&x);
for(ll j=0;j<=30;j++)
ll y=(x>>j)&1;
if(y==1) bit[j]++;
for(ll i=0;i<=30;i++)
if(bit[i]!=0) sum+=(1ll<<i);
printf("%lld\\n",sum);
int main()
int t;scanf("%d",&t);
while(t--) solve();
B. Avoid Local Maximums
题意:给你一个长度为n的序列,问最少经过多少次变换,保证没有局部最大值。局部最大值定义为严格大于两边的值。所有第一位和最后一位一定不能成为局部最大值。要求输出最少次数和变化后的序列。
思路:我们从2遍历到n-1,如果第i个数满足局部最大值的条件,我们就去变化i+1位置的数,这样变化最少。
变化最好是可以使得位置i、i+1、i+2当不能成为局部最大值。所以a[i+1]=max(a[i],a[i+2]。
(我初始加了边界
a
[
n
+
1
]
=
1
e
9
a[n+1]=1e9
a[n+1]=1e9,可以不加)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,sum,a[N];
void solve()
sum=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
a[n+1]=1e9;
for(int i=2;i<n;i++)
if(a[i]>a[i-1]&&a[i]>a[i+1])
sum++;
a[i+1]=max(a[i],a[i+2]);
printf("%d\\n",sum);
for(int i=1;i<=n;i++) printf("%d%c",a[i],(i==n)?'\\n':' ');
int main()
int t;scanf("%d",&t);
while(t--) solve();
C. Differential Sorting
题意:给一个长度为n的序列,可以进行m次操作
(
0
<
=
m
<
=
n
)
(0<=m<=n)
(0<=m<=n),每次操作选定一个三元组x,y,z,
(
1
<
=
x
<
y
<
z
<
=
n
)
(1<=x<y<z<=n)
(1<=x<y<z<=n),将
a
[
x
]
=
a
[
y
]
−
a
[
z
]
a[x]=a[y]-a[z]
a[x]=a[y]−a[z]。问是否可以最终将序列变成一个非降序列。不能输出-1,可以输出操作数和具体操作方案
思路:首先,必须保证
a
[
n
−
1
]
<
=
a
[
n
]
a[n-1]<=a[n]
a[n−1]<=a[n],因为这两处的值无法更改,让从后往前遍历,找到第一个非负数(位置idx),因为一个数减去一个负数,会使值增加,我们找到非负数,遍历时发现
a
[
i
]
>
a
[
i
+
1
]
a[i]>a[i+1]
a[i]>a[i+1],我们就可以选择i,i+1,idx,这样就可以使得
a
[
i
]
<
=
a
[
i
+
1
]
a[i]<=a[i+1]
a[i]<=a[i+1]
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,a[N];
struct nodeint x,y,z;;
vector<node>ans;
void solve()
ans.clear();
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
if(a[n]<a[n-1])puts("-1");return;
int idx=-1;
if(a[n]>=0) idx=n;
else if(a[n-1]>=0) idx=n-1;
for(int i=n-2;i>=1;i--)
if(a[i]<=a[i+1]) continue;
else
if(idx==-1) puts("-1");return;
ans.push_back(i,i+1,idx);
a[i]=a[i+1]-a[idx];
int len=ans.size();
printf("%lld\\n",len);
for(int i=0;i<len;i++) printf("%lld %lld %lld\\n",ans[i].x,ans[i].y,ans[i].z);
signed main()
int t;scanf("%lld",&t);
while(t--) solve();
D. Infinite Set
题意:给定n个不同的数,可以进行两种操作,就所有出现的数放入一个set,问值小于
2
p
2^p
2p的元素个数,答案
m
o
d
1
e
9
+
7
mod1e9+7
mod1e9+7
思路:
/*
看做二进制数
操作1:x*2+1 相当于 x1 加一位1
操作2:x*4 相当于x00 加两位0
并且任何数y都只可能由一种数转移而来不存在有两个数x1,x2进行若干次操作都可以得到y(x1,x2不能互相得到)
所以长度为len的二进制数可以由len-1的数进行操作1得到,由长度为len-2的数进行操作2得到,不会重复计算
另外有一些数不可能由以上操作得到 即 x为偶数且不是4的倍数,只能作为ai出现在集合里
或者能衍生出它的数不存在ai中,这些数单独计算
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+5;
const ll mod=1e9+7;
ll n,p,a[N],dp[N];
map<int,bool>mp;
int main()
scanf("%lld%lld",&n,&p);
for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
for(ll i=1;i<=n;i++)
ll now=a[i];
while(1)
if(now==1) break;
if(mp[now]) break;
if(now%2==1) now/=2;
else if(now%4==0) now/=4;
else break;
if(mp[now]) continue;
else
mp[a[i]]=true;
ll len=0;
while((1ll<<len)<a[i]) len++;
if((1ll<<len)==a[i]) dp[len+1]++;
else dp[len]++;
for(ll i=1;i<=p;i++) dp[i]=(dp[i]+dp[i-1]+dp[i-2])%mod;
ll sum=0;
for(ll i=1;i<=p;i++) sum=(sum+dp[i])%mod;
printf("%lld\\n",sum);
E. Cars
题意和思路在代码块内
//在水平线上有n辆车。有m种限制,每种限制为type,x,y
//当type==1时,第x辆车和第y辆车不能相遇
//当type==2时,第x辆车和第y辆车必须相遇一次
//问是否有方式,确定小车方向后,以及初始小车位置,使得满足所有限制
//先二分图匹配看是否存在方式,同时用point记录点的关系信息。point[i]存的都是必须在第i辆车右边的车的编号
//因为速度任意,所有不管是否相遇,方向都要相反
//col[i]==1:第i辆车向右 --->
//col[i]==0:第i辆车向左 <---
/*注释①
col[u]==1&&type==2
第u辆车方向向右(--->),此时第v辆车必须和第u辆车相遇,且已知第v辆车方向向左(<---)
那么第v辆车一定是在第u辆车的右边。 情况(--u-> <-v--)
col[u]==0&&type==1
第u辆车方向向左(<---),此时第v辆车必须和第u辆车不能相遇,且已知第v辆车方向向右(--->)
那么第v辆车一定是在第u辆车的右边。 情况(<-u-- --v->)
*/
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,col[N],pos[N],in[N],now;
bool vis[N],flag=true;
vector<int>point[N],nodes;
vector<pair<int,int> >edge[N];
void dfs1(int u,int color)
if(!flag) return;
nodes.push_back(u);
col[u]=color;
int len=edge[u].size();
for(int i=0;i<len;i++)
int type=edge[u][i].first;
int v=edge[u][i].second;
if(col[u]==col[v]) flag=false;return;
if((col[u]==1&&type==2)||(col[u]==0&&type==1)) point[u].push_back(v); //上面注释①
else point[v].push_back(u);
if(col[v]==-1) dfs1(v,color^1);
void dfs2(int u)
if(!flag) return;
in[u]=1;vis[u]Codeforces Round #772 (Div. 2)(ABCDE)
Codeforces Round #772 (Div. 2)(ABCDE)
DP二进制Codeforces Round #772 (Div. 2) D.Infinite Set
DP二进制Codeforces Round #772 (Div. 2) D.Infinite Set