Codeforces Round #521 (Div. 3) A B C D E

A. Frog Jumping

题目链接:https://codeforces.com/contest/1077/problem/A

题目大意:t组测试数据,从0开始,向前跳a,向后跳b,跳k次,输出最后所在的位置。

题解:大水题,直接输出就行了

int main()
{
	std::ios::sync_with_stdio(false);
	int t;
	while(cin>>t)
	{
		ll a,b,k;
		for(int i=1;i<=t;++i)
		{
			cin>>a>>b>>k;
			if(k%2)
				cout<<a*(k/2)-b*(k/2)+a<<endl;
			else
				cout<<(a-b)*(k/2)<<endl;
		}
	}
	
}

B. Disturbed People

题目链接:https://codeforces.com/contest/1077/problem/B

题目大意:n个数,每个数有0 || 1两种状态,0代表关灯睡觉,1代表开灯不睡觉,一个睡觉的如果两边都是开着灯的就会不开心(开灯的一直都开心),问最少熄灭多少盏灯能够让所有人都开心。

题解:贪心水题,对于每个不开心的人,熄灭后面的那一盏,因为只有后面的那一盏灯会对才会对后面的产生影响。

const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;

int vis[MAXN];

int main()
{
	std::ios::sync_with_stdio(false);
	int n;
	while(cin>>n)
	{
		clean(vis,0);
		for(int i=1;i<=n;++i)
			cin>>vis[i];
		int ans=0;
		for(int i=1;i<=n;++i)
		{
			if(vis[i]==0)//��ס��˯�� 
			{
				if(vis[i-1]&&vis[i+1])//��ס�������� 
				{
					ans++;
					vis[i+1]=0;
				}
			}
		}
		cout<<ans<<endl;
	}
}

C. Good Array

题目链接:https://codeforces.com/contest/1077/problem/C

题目大意:好数组的定义是:一个数组里面存在一个数,使得这个数组其他元素之和等于该数。我们可以从一个数组中去掉一个数来使它成为一个好数组,对于每个数组,输出所有能够去掉的一个元素使它能够构成一个好数组的元素(一次只能去掉一个)

题解:对于每个数组,求出它的和 sum,然后对于每个 a[i] 都判断一次,是否等于(sum-a[i])>>1,不等于则略过,等于则标记,最后输出即可。

//#pragma comment(linker, "/STACK:1024000000,1024000000") 

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>
#include<iostream>  
#include<algorithm>  
using namespace std;  

#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// ˮӡ 
//std::ios::sync_with_stdio(false);
const int MAXN=1e6+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;

int vis[MAXN];
int arr[MAXN];
int ansvis[MAXN];

int main()
{
	std::ios::sync_with_stdio(false);
	int n;
	while(cin>>n)
	{
		clean(vis,0);
		clean(arr,0);
		clean(ansvis,0);
		ll sum=0;
		for(int i=1;i<=n;++i)
		{
			cin>>arr[i];
			sum+=arr[i];
			vis[arr[i]]++;
		}
		int ans=0;
		ll res;
		for(int i=1;i<=n;++i)
		{
			res=sum-arr[i];//ȡ����һ���� 
			if(res>2*MAXN)
				continue;
			vis[arr[i]]--;//��λ�õ���-- 
			if(vis[res>>1] && res%2==0)//��������� && ����Ҫ�� 
			{
				ans++;
				ansvis[i]=1;
			}
			vis[arr[i]]++;//�ظ� 
		}
		if(ans)
		{
			cout<<ans<<endl;
			for(int i=1;i<MAXN;++i)
			{
				if(ansvis[i])
					cout<<i<<" ";
			}
			cout<<endl;
		}
		else
			cout<<0<<endl;
	}
}

D. Cutting Out

题目链接:https://codeforces.com/contest/1077/problem/D

题目大意:给出n个数,这n个数构成一个数组,可以从中提取出无限的有k个元素的数组,问提取后使原数组的元素个数最少的k个元素的数组使什么,随便输出一个就行。

题解:刚拿到题之后比较懵逼,试着用每次都除以二来找。。但是发现不行。。后来考虑用二分出符合要求的循环次数,然后遍历,发现可行,之后又复习了一下二分。。,大概思路就是:对于原数组,二分出最少的循环次数,然后找出符合要求的k个元素

//#pragma comment(linker, "/STACK:1024000000,1024000000") 
 
#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>
#include<iostream>  
#include<algorithm>  
using namespace std;  
 
#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);
const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;

int arr[MAXN],num[MAXN],ans[MAXN];

int judge(int mid)
{
	int res=0;
	for(int i=1;i<MAXN;++i)
	{
		if(num[i]>=mid)
			res+=num[i]/mid;//res新加入 num[i]/mid 个元素能重复出现mid轮 
	}
	return res;//res个字符重复出现mid轮 
}

int main()
{
	std::ios::sync_with_stdio(false);
	int n,k;
	while(cin>>n>>k)
	{
		clean(num,0);
		clean(ans,0);
		for(int i=1;i<=n;++i)
		{
			cin>>arr[i];
			num[arr[i]]++;
		}
		int l=1,r=n,mid,max_cyc;
		while(r>=l)
		{
			//cout<<mid<<" "<<l<<" "<<r<<endl;
			mid=(l+r)>>1;
			if(judge(mid)>=k)//res个字符重复出现mid轮 && 能够输出k个字符 
			{//应该轮数更少才行 
				max_cyc=mid;
				l=mid+1;
			}
			else
				r=mid-1;
		}
		//此时得出的轮数是max_cyc 
		int tot=0,cyc;
		for(int i=1;i<MAXN;++i)
		{
			cyc=num[i]/max_cyc;
			if(cyc>0)
			{
				for(int j=1;j<=cyc;++j)
				{
					ans[tot++]=i;
					if(tot==k)
						break;
				}
			}
			if(tot==k)
				break;
		}
		for(int i=0;i<k;++i)
			cout<<ans[i]<<" ";
		cout<<endl;
	}
}

E. Thematic Contests

题目链接:https://codeforces.com/contest/1077/problem/E

题目大意:给出一个数n,然后是n个数,每个数代表这个问题的种类,要求出一套题,每种问题的个数都是2倍的向上增加的,求出可以选择的最多的题目数量。

题解:由于ai的数据范围比较大,所以首先离散化一下数据,然后按照出现的次数排序,在之后,先选最多的,从后往前依次找/2的问题的个数,能找到则加上,找不到则说明这个问题的序列已经到了尽头,(注意一下,这个数要是偶数,因为如果它是奇数的话,就不能和前面的数构成二倍的关系)

//#pragma comment(linker, "/STACK:1024000000,1024000000") 
 
#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>
#include<iostream>  
#include<algorithm>  
using namespace std;  
 
#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);
const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;

int arr[MAXN],vis[MAXN];
map<int,int> mp;

int main()
{
	std::ios::sync_with_stdio(false);
	int n;
	while(cin>>n)
	{
		mp.clear();
		clean(arr,0);
		clean(vis,0);
		for(int i=1;i<=n;++i)
			cin>>arr[i];
		int k=1;
		for(int i=1;i<=n;++i)//数据离散化 
		{
			if(mp[arr[i]]==0)
				mp[arr[i]]=k++;
		}
		for(int i=1;i<=n;++i)//遍历数组,将它转换成出现的次数 
			vis[mp[arr[i]]]++;
		sort(vis,vis+k);//升序遍历 
		int ans=0;
		for(int i=1;i<=vis[k-1];++i)
		{
			int choose=k-1;//从后往前找 ,用最多的选上i 
			int num=i,res=0+num;//一开始选择i个问题 ,res=0+i 
			while(num%2==0&&choose>0)
			{
				num=num>>1;
				choose--;
				if(vis[choose]<num)
					break;
				res+=num;
			}
			ans=max(ans,res);
		}
		cout<<ans<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/84556212