Codeforces Round #760 (Div. 3)
- A. Polycarp and Sums of Subsequences
题目大意:集合\(a\)中有三个元素,\(a\)中元素组合后的和,构成了不含空集的七个元素的集合\(b\),集合\(b\)按升序排列,现在给出\(b\),求\(a\)
思路:\(b[1],b[2]\)肯定存在于\(a\),显然第三个值肯定是最大的\(b[7]-b[1]-b[2]\)
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int t;
int a[N];
int main(){
cin>>t;
while(t--){
for(int i=1;i<=7;i++) cin>>a[i];
int res1=a[1],res2=a[2],res3;
for(int i=3;i<=7;i++){
if((a[i]+res1+res2)==a[7]){
res3=a[i];
break;
}
}
cout<<res1<<" "<<res2<<" "<<res3<<endl;
}
return 0;
}
- B. Missing Bigram
题目大意:给出一个全为\(a/b\)组成的长度为\(n\)的字符串\(str\),现在取出所有相邻的\(m\)个二元字符,现在给出其中\(m-1\)个,求符合条件的原字符串
思路:如果相邻两个字符的头尾相同就拼上去,不同就直接加上下一个字符,最后如果字符串长度小于\(n\),加上\(a/b\)即可
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int t,n;
char a[N][5];
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<(n-2);i++){
for(int j=0;j<2;j++){
cin>>a[i][j];
}
}
string s;
s+=a[0];
for(int i=1;i<(n-2);i++){
if(a[i][0]!=a[i-1][1]) s+=a[i];
else s+=a[i][1];
}
if(s.size()<n) s+='a';
cout<<s<<endl;
}
return 0;
}
- C. Paint the Array
题目大意:给定一个数组\(a\),求是否存在一个\(d\),使得\(a_i\)能整除\(d\)且\(a_{i+1}\)就不能整除
思路:求一个奇数位的\(gcd\),判断所有偶数位是否都不整除\(gcd\),如果不成立,就再求一下偶数位\(gcd\),判断所有奇数位是否都不整除\(gcd\),都不成立即输出\(0\)
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int t,n;
ll a[N];
ll gcd(ll a,ll b){
if(!b) return a;
return gcd(b,a%b);
}
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
ll gcd1,gcd2;
int flag=1,flag2=1;
gcd1=a[1];
for(int i=1;i<=n;i+=2){
gcd1=gcd(a[i],gcd1);
}
for(int i=2;i<=n;i+=2){
if(a[i]%gcd1==0){
flag=0;
break;
}
}
if(flag){
cout<<gcd1<<endl;
flag2=0;
flag=0;
}
if(flag2){
flag=1;
gcd2=a[2];
for(int i=2;i<=n;i+=2){
gcd2=gcd(a[i],gcd2);
}
for(int i=1;i<=n;i+=2){
if(a[i]%gcd2==0){
flag=0;
break;
}
}
}
if(flag) cout<<gcd2<<endl;
else if(flag2) cout<<"0"<<endl;
}
return 0;
}
- D. Array and Operations
题目大意:给定一个数组\(a\),\(k\)次操作,每次取出两个数\(a_i\),\(a_j\),记\(res+=a_i/a_j\),操作结束后,\(res\)加上数组中剩余数的和,求\(min_{res}\)
思路:先将数组\(a\)排序一下,显然\(a_i<a_j\)时,\(res\)值不变是最优选择。我们可以发现
对于\(k\)次操作,我们取\(l=n-k\),\(r=n\),\(l,r\)每次前移时是最优解
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int t,n,k;
int a[N];
int main(){
cin>>t;
while(t--){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
ll ans=0;
sort(a+1,a+1+n);
int l=n-k,r=n;
while(k--){
ans=ans+(a[l]/a[r]);
a[r]=0;
a[l]=0;
l--;
r--;
}
for(int i=1;i<=n;i++) ans+=a[i];
cout<<ans<<endl;
}
return 0;
}
- E. Singers' Tour
题目大意:有\(n\)个小镇围成一个环,在第\(i\)个小镇有一个歌手\(i\)和持续时间为\(a_i\)的曲子,每位歌手按顺时针走遍这\(n\)个小镇,在每个城镇恰好举办一场音乐会。此外,在每个城镇,第\(i\)位歌手都受到启发,想出了一首持续\(a_i\)分钟的歌曲。 这首歌被添加到他的曲目中,以便他可以在其他城市演出。
因此,对于第\(i\)个歌手,在第\(i\)个城镇的音乐会将持续\(a_i\)分钟,在第\((i+1)\)个城镇的音乐会将持续\(2⋅a_i\)分钟,\(······\),在第\(((i+k)modn+1)\)个城镇音乐会的持续时间将是\((k+2)⋅a_i\),\(······\),在这个城镇\(((i+n−2)modn+1)\)个城镇音乐会的持续时间将是\(n⋅a_i\)分钟。
给定一个数组\(b\),其中\(b_i\)是第\(i\)个城镇中音乐会的总持续时间。求是否存在数组\(a\)满足条件。
思路:有条件我们可以列出一个线性方程组:
\(n\)个柿子相加得:\(\sum b_i=(1+2+···+n-1+n)*\sum a_i=\frac{n*(n+1)}{2}*\sum a_i\)
又有:\(b_{i+1}-b_i=\sum a_i-n*a_{i+1}\)
两式联立可得:\(a_{i+1}=\frac{\frac{2}{n*(n+1)}*\sum b_i-(b_{i+1}-b_i)}{n}\)
PS:得到\(a_{i+1}\)的通项后注意:记\(b_0=b_n\),这样遍历\(0\le i\lt n\)即可,要判断\(2*\sum b_i\)是否整除\(n*(n+1)\),判断\(\frac{2}{n*(n+1)}*\sum b_i-(b_{i+1}-b_i)\)是否大于\(0\)且整除\(n\)
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll t,n,b[N],a[N];
int main(){
cin>>t;
while(t--){
cin>>n;
int flag=1;
ll sum=0;
for(int i=1;i<=n;i++) {
cin>>b[i];
sum+=b[i];
}
if((sum*2)%(n*n+n)!=0) flag=0;
sum=sum*2/(n*n+n);
b[0]=b[n];
for(int i=0;i<n;i++){
ll tt=sum-(b[i+1]-b[i]);
if(tt<=0||tt%n!=0) {
flag=0;
break;
}
a[i+1]=tt/n;
}
if(!flag) cout<<"NO"<<endl;
else {
cout<<"YES"<<endl;
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
}
}
return 0;
}
- F. Reverse
对于一个二进制数\(x\),每次操作可以在它的末尾加一个\(0\)或者\(1\),然后将其翻转(自动去除前导\(0\))
现在给定两个正整数\(x\)和\(y\),\(\ (x,y\le 10^{18})\),问能否通过若干次操作后将\(x\)变成\(y\)
思路:每次操作有两种选择:\(+0\)就是直接翻转;\(+1\)就是\(x*2+1\)再翻转,肯定要通过\(dfs/bfs\)搜索来解决,用一个\(map\)来记录中间值是否已经出现过即可
Code:
\(dfs\):
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll x,y;
int flag;
map<ll,int> vis;
int get_bit(ll x){
int res=0;
for(;x;x>>=1) res++;
return res;
}
ll rev(ll x){
ll res=0;
for(;x;x>>=1) res=(res<<1)+(x&1);
return res;
}
void dfs(ll x){
vis[x]=1;
if(x==y) flag=1;
ll tt1=rev(x);
ll tt2=rev(x*2+1);
if(!vis[tt1]&&get_bit(tt1)<=get_bit(y)) dfs(tt1);
if(!vis[tt2]&&get_bit(tt2)<=get_bit(y)) dfs(tt2);
}
int main(){
cin>>x>>y;
flag=0;
dfs(x);
if(!flag)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
return 0;
}
\(bfs\):
#include <bits/stdc++.h>
#define ll long long
using namespace std;
template<class T>
inline void read(T &x){
x=0; char c; int sign=1;
do{ c=getchar(); if(c=='-') sign=-1;}while(!isdigit(c));
do{ x=x*10+c-'0',c=getchar();}while(isdigit(c));
x*=sign;
}
int get_bit(ll x){
int ret=0;
for(;x;x>>=1,ret++);
return ret;
}
ll Rev(ll x){
ll ret=0;
for(;x;x>>=1) ret=(ret<<1)+(x&1);
return ret;
}
ll xx,yy;
int main(){
read(xx),read(yy);
queue<ll> q;
map<ll,int> vis;
int des=get_bit(yy);
q.push(xx);
q.push(Rev(xx));
bool flag=0;
while(q.size()){
ll now=q.front(),revn;
revn=Rev(now);
int cnt=get_bit(now);
q.pop();
if(cnt<des&&vis.count(now)==0) q.push(Rev(now<<1|1));
if(cnt<des&&vis.count(revn)==0) q.push(Rev(revn<<1|1));
if(cnt==des) flag|=(now==yy||revn==yy);
vis[now]=1;
}
if(flag) puts("YES");
else puts("NO");
return 0;
}