Codeforces Round #636 (Div. 3)

Codeforces Round #636 (Div. 3)

A. Candies
題目大意

給定一個n,使得x + 2x + 4x + … + 2^k-1 x = n 成立,求x,且滿足k > 1。

Solution

求一個係數1 + 2 + 4 + 2^k-1 能被n整除,n/係數 即爲答案。

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int SZ = 1e5 + 7;
const int INF = 0x3f3f3f3f;
ll n;
 
int main()
{
	int T;
	scanf("%d",&T);
	while(T --)
	{
		scanf("%lld",&n);
		ll sum = 3,t = 2;
		while(n % sum != 0)
		{
			t *= 2;
			sum += t;	
		}
		printf("%lld\n",n/sum);
	}
	return 0;
}
 

B. Balanced Array

題目大意

給定一個n,構造一個長度爲n的數列,n保證是一個偶數,使得前n/2個元素全爲偶數,後n/2個元素全爲奇數,並且每個數字都不一樣,且前半段和後半段的和相同。

Solution

前半段的和必然是偶數,後半段如果爲奇數個,和是奇數,不合法,所以n/2必須是偶數。
如果合法,前半段按2,4,6,… 後半段按1, 3 , 5… 這樣排列,最後一個數字加上 n/2 - 1 即可。
代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int SZ = 1e5 + 7;
const int INF = 0x3f3f3f3f;
int n;
int T;
 
 
int main()
{
	int i;
	cin>>T;
	while(T--)
	{
		scanf("%d",&n);
		if ((n / 2) % 2 == 1){printf("NO");}
		else
		{
			printf("YES\n");
			for(i=1;i<=n/2;i++)
			printf("%d ",2*i);
			for(i=1;i<n/2;i++)
			printf("%d ",2*i-1);
			printf("%d",2*i+(n/2-1));
		}
		printf("\n");
	}
}

C. Alternating Subsequence

題目大意

給定一段序列,要求選出一個最長序列,使得序列中必須滿足異號相鄰,同號不得相鄰,如果有多個最長,選出和最大的,輸出和。

Solution

出現異號的就選擇,同號的就找較大的一個,然後繼續找異號的,再把最後一個加上即可。

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int SZ = 2e5 + 7;
const int INF = 0x3f3f3f3f;
int n,f,num[SZ];
ll s,sum; 

int main()
{
	int T;
	scanf("%d",&T);
	while(T --)
	{
		f = 0,sum = 0;
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++)
		{
			scanf("%d",&num[i]);
			if (f == 0)
			{
				if (num[i] < 0) f = -1;
				else f = 1;
				s = num[i];
			}
			if (f == 1 && num[i] < 0)
			{
				sum += s;
				s = num[i];
				f = -1;
			}
			if (f == -1 && num[i] > 0)
			{
				sum += s;
				s = num[i];
				f = 1;
			}
			if (num[i] > s)s = num[i];
		}
		sum += s;
		printf("%lld\n",sum);
	}
	return 0;
}

D. Constant Palindrome Sum

題目描述

給定一個長度爲n的序列,其中任意一個數字的範圍爲1 <= ai <= k,現在你可以更改其中任何的數字,使得仍滿足1 <= ai <= k,且 a[i] + a[n - i + 1] = x,對於n/2對組合x必須相同,問最少修改次數。

Solution

對於每一組,只有3種選擇,不改,改一個,改兩個。
對於一組數,修改一次可達到的範圍 : min(num[i],num[n - i + 1]) + 1 到 max(num[i],num[n - i + 1]) + k。且中間要挖去不需要修改的點。變到其他值則需要修改2次,總範圍從2到2 * k。那麼做差分,再求一次前綴和,即爲改到當前x所需要修改的次數,選擇一個最小的即爲答案。

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int SZ = 2e5 + 10;
const int INF = 0x3f3f3f3f;
ll k,id,n,num[SZ];
ll vis[SZ << 1]; 
int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		memset(vis,0,sizeof(vis));
		scanf("%lld%lld",&n,&k);
		for(int i = 1;i <= n;i ++)
			scanf("%lld",&num[i]);
		for(int i = 1;i <= n/2;i ++ )
		{
			vis[1] += 2;
			vis[min(num[i],num[n - i + 1]) + 1] -= 2;
			vis[min(num[i],num[n - i + 1]) + 1] += 1;
			vis[num[i] + num[n - i + 1] + 1] += 1;
			vis[num[i] + num[n - i + 1]] -= 1;
 			vis[max(num[i],num[n - i + 1]) + k + 1] -= 1;
 			vis[max(num[i],num[n - i + 1]) + k + 1] += 2;
 			vis[2 * k + 1] -= 2;
		}
		id = 1;
		for(int i = 2;i <= k * 2;i ++ )
		{
			vis[i] += vis[i - 1];
			if(vis[i] < vis[id])
			id = i;
		}
		printf("%lld\n",vis[id]);
	}
	return 0;
}

2020.4.23

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章