1. 程式人生 > >Codeforces Round #521 (Div. 3) A B C D E

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;
	}
}