Codeforces Round #760 (Div. 3)

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\)满足条件。

思路:有条件我们可以列出一个线性方程组:

\[ \begin{cases} b_1=a_1+n*a_2+(n-1)*a_3+···+3*a_{n-1}+2*a_n\\ \qquad\qquad\qquad\qquad\qquad······\\ b_i=i*a_1+···+a_i+···+(i+2)*a_{n-1}+(i+1)*a_n\\ \qquad\qquad\qquad\qquad\qquad······\\ b_n=n*a_1+(n-1)*a_2+(n-3)*a_3···+2*a_{n-1}+a_n \end{cases} \]

\(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;
}
posted @ 2021-12-15 23:27  Wraith-Fiee  阅读(81)  评论(0)    收藏  举报