Codeforces Round #636 (Div. 3)(A-D題解)

這是一個悲傷的夜晚,做題太慢了,導致d題甚至都沒時間做了,早上起來發現C還被踩了。
在這裏插入圖片描述
在這裏插入圖片描述
題目大意:
給你一個n,還給你一個等式x + 2x + 4x + 8x + …+2^(k - 1)x = n,其中k(>1)
思路:
一個水題,因爲題目保證答案有解,直接枚舉k解這個一元方程即可。(一個水題寫了20多分鐘啊啊。。。還是做題太少)
代碼:

#include<bits/stdc++.h>
using namespace std;
 
const int maxn = 1e5 + 10;
typedef long long int ll;
void solved(){
	int t;cin>>t;
	while(t--){
		ll n;cin>>n;
		ll cnt = 1;
		for(int i = 1; i <= 100; i++){
			cnt += (1<<i);
			//cout<<cnt<<endl;
			if(n % cnt == 0){
				//cout<<n<<" "<<cnt<<endl;
				cout<<(n / cnt)<<endl;break;
			}
		}  
	}
}
int main(){
	solved();
	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述
題意:
給你一個n(保證n是偶數),要你構造這樣的一個序列,前面n/2個元素是偶數,後面n/2個是奇數,並且前面n/2和後面n/2個數之和相等,並且每個數是唯一的。
思路:
一個簡單的構造,直接前面n/2個用公差爲2的等差數列構造即可,首項爲2,後面n/2 - 1個用首項爲1公差爲2的等差數列構造即可。要使得構造成功n/2得是一個偶數,這樣兩邊的和才能均攤。那麼我們可以知道n/2必定是一個偶數,因爲後面n/2項和會少於前面n/2項,那麼只需要用前面n/2項和減去後面n/2-1項和即可。顯然第n項必定是一個奇數。

這個寫複雜了,當時場上題意理解錯了,我以爲只有第一個n/2是偶數,第二個n是奇數就行了。。。所以後面改的代碼思路有一點點亂。這個可以直接輸出就行了。
代碼:

#include<bits/stdc++.h>
using namespace std;
 
const int maxn = 2e5 + 10;
typedef long long int ll;
ll a[maxn];
void solved(){
	int t;cin>>t;
	while(t--){
		ll n;cin>>n;
		if(n == 2){
			cout<<"NO"<<endl;continue;
		}
		bool flag = false;
		if((n/2)%2==0)flag = true;
		if(flag){
			cout<<"YES"<<endl;
			ll l = 2;
			int pos = 1;
			for(int i = 1; i <= n / 2; i++){
				a[i] = l;
				l += 2;
			}
			ll r = 1;
			ll sum = 0;
			for(int i = n/2+1;i <= n; i++){
				a[i] = r;
				sum += a[i];
				r += 2;
			}
			sum -=a[n];
			a[n] = (n/2)*(2+a[n/2])/2-sum;
			for(int i = 1; i <= n; i++){
				cout<<a[i]<<" ";
			}
			cout<<endl;
		}else{
			cout<<"NO"<<endl;
		}
	}
}
int main(){
	solved();
	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述

題目大意:
給你一個序列,要你在滿足長度最大的情況下輸出這個序列的最大值。就是說你要在一段連續的子序列選數,就是一個負數一個正數這樣去選。
思路:
這個題很簡單,O(n)暴力模擬一下就行了,大概幾分鐘就寫完了。
早上起來發現被hack了,原因爲while()裏面還要滿足i<=n(我真是個傻子)
代碼:

#include<bits/stdc++.h>
using namespace std;
 
const int maxn = 2e5 + 10;
typedef long long int ll;
ll a[maxn];
void solved(){
	int t;cin>>t;
	while(t--){
		int n;cin>>n;
		for(int i = 1; i <= n; i++)cin>>a[i];
		ll ans = 0;
		vector<ll>ve;
		for(int i = 1; i <= n;){
			ll m = -1e18,M = -1e18;
			bool f1 = false,f2 = false;
			while(i <= n && a[i] > 0){
				if(a[i] > M){
					M = a[i];f1 = true;
				}
				i++;
			}
			while(i <= n && a[i] < 0){
				if(a[i] > m){
					m = a[i];f2 = true;
				}
				i++;
			}
			if(f1)
			ve.push_back(M);
			if(f2)
			ve.push_back(m);
		}
		for(int i = 0; i < ve.size();i++){
			ans += ve[i];
		}
		cout<<ans<<endl;
	}
}
int main(){
	solved();
	return 0;
}

在這裏插入圖片描述
在這裏插入圖片描述
題目大意:
給你n個小於等於k的數,要你構造出一個ai + a(n - i + 1) = x這樣的序列。你可以用[1,k]中的數去替換掉ai。
思路:
考慮每隊ai和a(n- i + 1)替換掉其中一個可以得到的和,與替換掉2個可以得到的和。
替換掉其中一個我們可以得到他們的和的取值範圍爲[min(ai,a(n - i + 1))+ 1,max(ai,a(n - i + 1)) + k]。
替換掉兩個我們可以得到他們和的取值範圍爲[2,min(ai,a(n - i + 1))]∪[max(ai,a(n - i + 1)) + k + 1, 2 * k]。
如果不用替換就是ai + a(n - i + 1)。我們令這個區間 -1.因爲它不用替換嘛,但是我們替換1的時候給計算進去了,所以這裏需要弄出來。
然後從[2, 2 * k]中選最小值,就是所有組爲了得到這個數需要替換的最少次數。
因爲這裏需要用到區間加法,但是n=2e5,如果暴力O(n^2)會超時,所以這裏我們需要用到差分數組,如果不懂的可以百度一下。或者樹狀數組線段樹都行。
代碼:

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

const int maxn = 2e5 + 10;
typedef long long int ll;
ll a[maxn],s[maxn << 1];
void add(int l,int r,int v){
	s[l]+=v;s[r+1]-=v;
}
void solved(){
	int t;cin>>t;
	while(t--){
		int n,k;cin>>n>>k;
		for(int i = 2; i <= 2 * k; i++)s[i] = 0;
		for(int i = 1; i <= n ;i++)cin>>a[i];
		for(int i = 1; i <= n/2 ;i++){
			int x = a[i];
			int y = a[n - i + 1];
			if(x > y)swap(x,y);
			add(x+y,x+y,-1);
			add(x+1,y+k,1);
			add(y+k+1,2*k,2);
			add(2,x,2);
		}
		ll ans = 1e18;
		for(int i = 2; i <= 2 * k ;i++){
			s[i] += s[i - 1];ans = min(ans,s[i]);
		}
		cout<<ans<<endl;
	}
}
int main(){
	solved();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章