Codeforces Round #631 (Div. 2) - Thanks, Denis aramis Shitov!

A。傻逼題

#include<bits/stdc++.h>
#define MAXN 405
using namespace std;
 
int T,n,a[MAXN],judge[MAXN],x;
int main(){
	cin>>T;
	while(T--){
		cin>>n>>x;memset(judge , -1 , sizeof(judge));
		for(int i = 1 ; i <= n ; i++){cin>>a[i];judge[a[i]] = 1;	}
		for(int i = 1 ; i <= 400 ; i++){
			if(judge[i] == (-1) && x == 0){cout<< i - 1 <<endl;break;}
			if(judge[i] == (-1))x--;
		}
	}
}

B。給你一串數字,問你這串數字能分成兩段,且兩端是個1—n的排列的方案數,並且輸出方案
顯然:一個段能是一個1—n的排列,只有當它的最大值等於這段內的不同的元素個數
那麼很顯然,可以根據這個從左往右掃,在反向掃一遍即可

#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
 
int T,n,a[MAXN],judge[MAXN],ok[MAXN],ok2[MAXN],sum,ans,maxl1[MAXN],maxl2[MAXN];
int main(){
	cin>>T;
	while(T--){
		cin>>n;
		for(int i = 1 ; i <= n ; i++)cin>>a[i];
		for(int i = 1 ; i <= n ; i++)judge[a[i]] = ok[i] = ok2[i] = (-1);
		sum = maxl1[0] = maxl2[n + 1] = 0;
		for(int i = 1 ; i <= n ; i++){
			if(judge[a[i]] == (-1)){
				judge[a[i]] = 1;
				maxl1[i] = max(maxl1[i - 1] , a[i]);
				sum++;
				if(sum == maxl1[i])ok[i] = 1;
			}
			else break;	
		}
		sum = 0;
		for(int i = n ; i >= 1 ; i--){
			if(judge[a[i]] == (-1) || judge[a[i]] == 1){
				judge[a[i]] = 2;
				maxl2[i] = max(maxl2[i + 1] , a[i]);
				sum++;
				if(sum == maxl2[i])ok2[i] = 1;
			}	
			else break;
		}
		ans = 0;
		for(int i = 1 ; i < n ; i++){
			if(ok[i] == 1 && ok2[i + 1] == 1){
				ans++;
			}
		}
		cout<<ans<<endl;
		for(int i = 1 ; i < n ; i++){
			if(ok[i] == 1 && ok2[i + 1] == 1){
				cout<<maxl1[i]<<" "<<maxl2[i + 1]<<endl;
			}
		}
	}
}

C,有m次操作,每次可以覆蓋一段長度爲Li的區間,讓你輸出一個方案使得1—n都被覆蓋,且每種顏色都出現

一個很顯然的判定不合法的條件,長度和<n
對於無解判斷,只要對於每種顏色,前面儘量少放,然後還是放不下,就無解
可以考慮每次只給每種顏色留一個空格,然後每次讓每一個顏色儘量往後面覆蓋即可

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

long long n,m,sum,len[MAXN],ans[MAXN],maxl;

void init(){
	cin>>n>>m; sum = maxl = 0;
	for(int i = 1 ; i <= m ; i++){
		cin>>len[i];
		sum += len[i];
	}
	if(sum < n){cout<<-1<<endl;exit(0);}
	for(int i = 1 ; i <= m ; i++){
		if(n < (i + len[i] - 1)){
			cout<<-1<<endl;
			exit(0);	
		}
	}
	for(int i = 1 ; i <= m ; i++)ans[i] = i;
	maxl = n;
	for(int i = m ; i >= 1 ; i--){
		if(i + len[i] - 1 <= maxl)ans[i] = maxl - len[i] + 1 , maxl = maxl - len[i];
		else break;
	}
	for(int i = 1 ; i <= m ; i++){
		cout<<ans[i]<<" ";
	}
}

int main(){
	init();
}

D.給你一個d,問你 構造一個遞增序列 最後一項小於等於d,並且他們的異或前綴和序列也是遞增的方案數
打表發現
bi滿2logbi+1<=a(i+1) 對於bi遞增,每次應該滿足2^{logbi + 1} <= a(i + 1)

於是乎,可以把每次分個組
(1),(2,3),(4,5,6,7),(8,9,10,11,12,13,14,15)。。。然後每組選一個就好了

注意邊界

#include<bits/stdc++.h>
using namespace std;

int T;
long long m,d,f[105],s,tot,b[105],g;

int main(){
	cin>>T;g = 0;
	while(T--){
		cin>>d>>m;
		s = 1;
		tot = 0;
		while(s <= d){
			tot++;
			b[tot] = min(d - s + 1 , s);
			s = s << 1;
		}
		for(int i = 1 ; i <= tot ; i++){
			f[i] = (f[i - 1] * b[i]) % m+ (f[i - 1]) % m + b[i] % m;
		}
		cout<<max(f[tot] % m , g)<<endl;
	}
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章