Codeforces Round 951 (Div. 2)

4 篇文章 0 订阅

A. Guess the Maximum

题意:

给定一个长度为n的整数数组,问数组中是否存在一个子数组满足子数组的最大值大于 k k k,若存在则爱丽丝获胜,否则鲍勃获胜,帮助爱丽丝找出最大值 k k k
,保证她赢。

题解:

遍历长度为 2 2 2的子数组,找出每个子数组的最大值,然后在最大值中找出最小值 − 1 -1 1就是答案。

代码:

#include <iostream>
#include<algorithm>

using namespace std;

const int N=5e4+10;

int a[N];

void solve(){
	int n;
	
	cin>>n;
	
	for(int i=0;i<n;i++) cin>>a[i];
	
	int k=max(a[0],a[1]);
	int x;
	
	for(int i=0;i<n-1;i++){
		x=max(a[i],a[i+1]);
		k=min(k,x);
	}
	k--;
	
	cout<<k<<endl;
}
int main()
{
	int t;
	
	cin>>t;
	
	while(t--) solve();
	
	return 0;
}

B. XOR Sequences

题意:

给出 x x x y y y,若存在两个长度无穷数组 a a a b b b,满足 a i = i ⊕ x a_{i}=i \oplus x ai=ix, b j = j ⊕ y b_{j}=j \oplus y bj=jy,问数组 a a a和数组 b b b最长的公共子段的长度。

题解:

结论:将x和y写成对应的二进制数字,对应二进制字串最长的后缀长度为 t t t,则 2 t 2^t 2t即为答案。
证明:设 x x x的二进制串为 a a a y y y的二进制串为 b b b i i i的二进制串为 c c c j j j的二进制串为 d d d,对于相同的后缀只需要 c i = d i c_{i}=d_{i} ci=di(可以任取0/1),对于剩余的前缀只需要满足 c i ⊕ d i c_{i} \oplus d_{i} cidi= b i ⊕ a i b_{i} \oplus a_{i} biai即可,a和b可能存在不止一个长度为 2 t 2^t 2t的公共子串。

代码:

#include <iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<math.h>

using namespace std;

#define int long long

const int N=50;

int a[N],b[N];

void solve(){
	for(int i=0;i<=50;i++) a[i]=0,b[i]=0;
	
	int x,y;
	cin>>x>>y;
	int count1=0,count2=0;
	while(x){
		a[count1]=x%2;
		x/=2;
		count1++;
	}
	while(y){
		b[count2]=y%2;
		y/=2;
		count2++;
	}
	
	int ans=1;
	for(int i=0;i<max(count1,count2);i++){
		if(a[i]==b[i]) ans*=2;
		else break;
	}
	cout<<ans<<endl;
}
signed main()
{
	int t;
	
	cin>>t;
	
	while(t--) solve();
	
	return 0;
}

C. Earning on Bets

题意:

有人提议让您玩一个游戏。在这个游戏中,有 n n n 种可能的结果,对于每一种结果,您都必须下注一定整数的硬币。如果 i i i 的结果是赢,您将获得与您在该结果上所下注金额相等的硬币,再乘以 k i k_i ki 。请注意, n n n 个结果中只有 1 1 1个结果是赢的。
你的任务是决定如何分配硬币,以便在出现任何获胜结果时都能获胜。更正式地说,你在所有结果上投注的硬币总数必须**严格地小于每个可能获胜的结果所得到的硬币数量。

题解:

二分找出总下注的硬币数,然后根据规则分配即可。

代码:

#include<iostream>
#include<algorithm>
#define int long long

using namespace std;

const int N=110;
int a[N],b[N];
int n;

bool check(int x) {
	int sum = x ;
	for (int i = 1; i <= n; i ++) {
		sum -= x / a[i];
	}
	return sum >= n;
}

void solve(){
	cin>>n;
	
	for(int i=1;i<=n;i++) cin>>a[i];
	
	int l = n - 1, r = n * (int)1e9 + 1;
	
	while(l<r){
		int mid=(l+r)>>1;
		if(check(mid)) r=mid;
		else l=mid+1;
	}
	int ans=l;
	int sum=ans;
	
	if(ans==n-1||ans==n*(int)1e9+1){
		cout<<"-1"<<endl;
		return;
	}
	for(int i=2;i<=n;i++){
		b[i]=ans/a[i]+1;
		sum-=b[i];
	}
	b[1]=sum;
	for(int i=1;i<=n;i++) cout<<b[i]<<" ";
	cout<<endl;
}
signed main(){
	int t;
	
	cin>>t;
	
	while(t--) solve();
	
	return 0;
}

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值