Codeforces Round #494 (Div. 3) (ABCDE) 题解

本文详细解答了Codeforces Round #494 (Div. 3) 中的ABCDE五道题目。A题通过统计最大出现次数解决;B题依据01序列性质讨论构造;C题使用暴力求解最大平均值子序列;D题利用2的倍数特性进行二进制拆分求解;E题先构造直径,再扩展成树,确保节点深度限制。
摘要由CSDN通过智能技术生成

题目链接:http://codeforces.com/contest/1003

A题题意:给定N个值,每个集合只能放不相同的数,问把所有值放进去最少需要多少个集合。

A题题解:直接暴力统计最多出现的数的次数即可。

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 1e5+7;
int a[105];
int n;
int main(int argc, char const *argv[])
{
	cin>>n;
	int ans = 0;
	_for(i,1,n)
	{
		int x;
		cin>>x;
		a[x]++;
		ans=max(ans,a[x]);
	}
	cout<<ans<<endl;
	return 0;
}

B题题意:给定a,b,x三个数,构造一个长度为a+b的数列,其中0的个数等于a,1的个数等于b,a[i]!=a[i+1]的个数等于x。

B题题解:对x分奇偶分情况讨论,然后在两边将多余的01输出即可。

AC代码:

/*
* @Author: 王文宇
* @Date:   2018-07-03 22:40:50
* @Last Modified by:   王文宇
* @Last Modified time: 2018-07-03 23:04:11
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 1007;
char s[maxn];
int a,b,x;
int main(int argc, char const *argv[])
{
	cin>>a>>b>>x;
	int now = 1;
	int l = x;
	if(x&1)
	{
		if(a>b)
		{
			while(x>1)
			{
				a--;
				b--;
				x-=2;
			}
			while(a--)cout<<0;
			while(l>1)
			{
				cout<<"10";
				l-=2;
			}
			while(b--)cout<<1;
			cout<<endl;
		}
		else
		{
			while(x>1)
			{
				a--;
				b--;
				x-=2;
			}
			while(b--)cout<<1;
			while(l>1)
			{
				cout<<"01";
				l-=2;
			}
			while(a--)cout<<0;
			cout<<endl;			
		}
	}
	else
	{
		if(a>b)
		{
			a-=x/2;
			b-=x/2;
			while(a>1)
			{
				cout<<"0";
				a--;
			}
			while(x>0)
			{
				cout<<"01";
				x-=2;
			}
			while(b--)cout<<"1";
			cout<<0<<endl;
		}
		else
		{
			b-=x/2;
			a-=x/2;
			while(b>1)
			{
				cout<<"1";
				b--;
			}
			while(x>0)
			{
				cout<<"10";
				x-=2;
			}
			while(a--)cout<<"0";		
			cout<<1<<endl;	
		}
	}
	return 0;
}

C题题意:给定N个数值和K,求一个长度不小于K的子序列,使其平均值最大。

C题题解:因为n<=5000,所以n^2暴力即可。

AC代码:

/*
* @Author: 王文宇
* @Date:   2018-07-03 23:11:04
* @Last Modified by:   王文宇
* @Last Modified time: 2018-07-03 23:19:36
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 5005;
int n,k;
double ans;
int a[maxn];
int sum[maxn];
int main(int argc, char const *argv[])
{
	cin>>n>>k;
	_for(i,1,n)
	{
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
	}
	_for(i,0,n-k)
	{
		_for(j,i+k,n)
		{
			int h = sum[j]-sum[i];
			double now = (double)h/(double)(j-i);
			ans = max(now,ans);
		}
	}
	printf("%.15lf\n",ans);
	return 0;
}

D题题意:给定一个只包含2的倍数的数组,然后给定Q个询问,对于每次询问的整数找到取最少的数组中的数的和等于被询问数,无法构成输出-1

D题题解:将给定的数拆成2进制统计每个进制然后对于每个询问暴力即可。

AC代码:

/*
* @Author: 王文宇
* @Date:   2018-07-03 23:47:28
* @Last Modified by:   王文宇
* @Last Modified time: 2018-07-04 00:49:17
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 2e5+7;
int n,q;
int a[maxn],num[maxn];
int main(int argc, char const *argv[])
{
	cin>>n>>q;
	_for(i,1,n)
	{
		cin>>a[i];
		int k = -1;
		while(a[i])
		{
			k++;
			a[i]/=2;
		}
		num[k]++;
	}
	_for(i,1,q)
	{
		int x;
		cin>>x;
		int ss = 0;
		int now = 0;
		int ok = 0;
		long long k = 1;	
		long long next = (long long)x;
		while(k<=next)
		{
			k*=2;
			now++;
		}
		while(next>0)
		{
			k/=2;
			//cout<<now<<endl;
			now--;
			if(k>next)continue;
			if(num[now]*k>=next)
			{
				int h = next/k;
				next-=k*h;
				ss+=h;
			}
			else
			{
				ss+=num[now];
				next-=num[now]*k;
			}
			if(now==-1)
			{
				ok = 1;
				break;
			}	
		}
		if(ok||next<0)cout<<"-1"<<endl;
		else cout<<ss<<endl;
	}
	return 0;
}

E题题意:给定n,d,k,构造一棵无向树,结点个数为n,直径为d,每个结点的深度不大于k。

E题题解:首先特判不存在的情况,然后先构造出直径,然后在直径上尽可能的加边即可。最后判断加的边是不是等于n-1即可。

AC代码:

/*
* @Author: 王文宇
* @Date:   2018-07-03 23:34:42
* @Last Modified by:   王文宇
* @Last Modified time: 2018-07-04 04:02:26
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 4e5+7;
int n,d,k,now;
vector<pair<int,int> > Q;
vector<int> E[maxn];
void dfs(int x,int y,int z)
{
	if(z==y)return;
	for(int i=0;i<k-1-(y==0)&&now<n;i++)
	{
		now++;
		int u = now;
		Q.push_back(make_pair(x,u));
		dfs(u,y+1,z);
	}
}
int main(int argc, char const *argv[])
{
	cin>>n>>d>>k;
	if(n<(d+1))
	{
		cout<<"NO"<<endl;
		return 0;
	}
	if(k==1)
	{	
		if(d==1&&n==2)cout<<"YES\n1 2"<<endl;
		else cout<<"NO"<<endl;
		return 0;
	}
	now = d+1;
	_for(i,1,d)
	{
		E[i].push_back(i+1);
		Q.push_back(make_pair(i,i+1));
	}
	_for(i,1,d+1)
	{
		dfs(i,0,min(i-1,d+1-i));
	}
	if(now<n)
	{
		cout<<"NO"<<endl;
		return 0;
	}
	cout<<"YES"<<endl;
	_for(i,0,n-2)cout<<Q[i].first<<" "<<Q[i].second<<endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值