Codeforces Round #781 (Div. 2)(补)

A. 取特殊情况 1 n-3 1 1

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		cout<<'1'<<' '<<n-3<<' '<<'1'<<' '<<'1'<<endl;
	}
 } 

B. 记录出现次数最多的数出现了多少次  每次进行一次1操作 就判断进行几次二操作 要是没有打到目的数组 就再次循环找

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int xi=0;
		int n,x;
		cin>>n;
	    map<int,int>mp;
	    for(int i=0;i<n;i++)
	    {
	    	cin>>x;
	    	mp[x]++;
	    	if(mp[x]>mp[xi])xi=x; 
		}
		int sum=mp[xi];
		int ans=0;
		while(sum<n)
		{
			ans++;
			if(sum*2>n)ans+=n-sum;
			else ans+=sum;
			sum*=2;
		}
		cout<<ans<<endl;
	}
 } 

C. 二分 第一种感染就是感染他的兄弟(相同跟的) 第二种感染就是我们可以任意指定 所以我们就贪心的去想 我们肯定是先感染兄弟多的 让他一直可以进行1 操作 如果一共有cnt次操作 那么我么能感染的第一个最大就可以是进行了cnt-1次操作一 感染的第二个最大就是进行了cnt-2次操作二 我们只需再加上操作二的次数 即cnt的次数 进行二分答案即可

#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define pb push_back
const int INF=0x3f3f3f3f;
const int N=1e6+10,M=1e6+10;
const int maxn=2e5+10;
vector<int> g[maxn];
int n,cnt,b[maxn]; 
bool check(int mid){
	int maxx=0;
	for(int i=1,j=mid-1;i<=cnt;i++,j--){
		maxx+=max(0,b[i]-j);
	}
	return mid-cnt>=maxx;
}
void solve(){
	int n;cin>>n;
	for(int i=1;i<=n;i++)g[i].clear();
    for(int i=2;i<=n;i++){
		int x;cin>>x;
		g[x].pb(i);
	}
	cnt=1;b[1]=0;
	for(int i=1;i<=n;i++){
		if(g[i].size()){
			b[++cnt]=g[i].size()-1;
		}
	}
	sort(b+1,b+1+cnt,greater<int>());
	int l=cnt,r=n;
	while(l<r){
		int mid=l+r>>1;
		if(check(mid))r=mid;
		else l=mid+1;
	} 
	cout<<r<<'\n';
}
signed main(){
	ios::sync_with_stdio(false);
    cin.tie(0);
	int t;cin>>t;
	//int t=1;
	while(t--){
		solve();
	}
} 

D. 交互题  题意是 我们找出x 通过询问 gcd(a+x,b+x) 因为不超过30次 我们可以想到位运算 (这玩意你咋二分) 位运算的话就是每次都确定x的一位 那么怎么判断这一位是1还是0呢 我们就可以用 000==2的3次方 但是100 不是2的3次方 如果我们想知道第i位是不是1 我们就可以更新他的后缀 让他变成1000 的形式 再用一个2的i次方加上他 看看他是不是进位 如果进位就是1 否则就是0  我们就可以每次记录ansi 表示i位的查询gcd(x−ansi+2i+1,x−ansi+2i+1+2i+2)=gcd(x−ansi+2i+1,2i+2) 来确定第 i+1 位的值

#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define pb push_back
#define ll long long
const int INF=0x3f3f3f3f;
const int N=1e6+10,M=1e6+10;
const int maxn=2e5+10;
vector<int> g[maxn];
int n,cnt,b[maxn]; 
ll A[35];
void init(){
	ll num=1;
	for(int i=0;i<=30;i++){
		A[i]=num,num*=2;
	}
}
void solve(){
	ll res,ans=0;
	for(int i=0;i<30;i++){
		ll a=A[i]-ans,b=A[i]+A[i+1]-ans;
		cout << "? " << a << ' ' << b << endl;
		cin>>res;
		if(res==A[i+1])
		ans^=(1ll<<i); 
	}
	cout << "! " << ans << endl;
}
signed main(){
	ios::sync_with_stdio(false);
    cin.tie(0);
    init();
	int t;cin>>t;
	//int t=1;
	while(t--){
		solve();
	}
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值