Codeforces Round #636 (Div. 3) 题解

题目链接

A - Candies

题目大意:给你一个 n n n,你需要一个整数 x x x使所给式子的k为大于 1 1 1的整数。

题解:只需要从 2 2 2开始枚举 k k k,判断 n n n是不是能够整除当前系数。

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
 
 
void solve()
{
int n;
scanf("%d",&n);
int va=3,temp=4;
while(1)
{
	if(n%va==0){
		printf("%d\n",n/va);
		return;
	}
	va+=temp;
	temp*=2;
}
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

B - Balanced Array

题目大意:给你一个正偶数 n n n,让你构造一个长度为 n n n的数组,前一半为偶数,后一半为奇数,并且这两部分的和相等。还要求每个元素各不相同。

题解:首先如果 n n n不能被4整除,那么前一半与后一半的和必定不同奇偶,直接输出NO。其他情况我们只需要从小到大安排数字,在最后一个奇数补齐所缺的值使得两部分和相等。

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
 
int ans[maxn];
void solve()
{
int n;
scanf("%d",&n);
if(n%4!=0)
	printf("NO\n");
else {
	printf("YES\n");
	for(int i=1;i<=n/2;i++)
	{
    ans[i]=2*i;
	}
	for(int i=n/2+1;i<=n-1;i++)
	{
    ans[i]=2*(i-n/2)-1;
	}
	ans[n]=n/2-1+ans[n/2];
	for(int i=1;i<=n;i++)
	{
		if(i==n)
			printf("%d\n",ans[i]);
		else printf("%d ",ans[i]);
	}
}
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

C - Alternating Subsequence

题目大意:给你一个序列,你需要在这个序列中找相邻元素不同符号的最长子序列,在所有这样最长的最长子序列中,你要找出其中子序列的和最大的。

题解:在原序列中每一段连续的相同符号的数分为一个区块,在每个区块去一个最大值加起来就是最优答案。

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
 
int a[maxn];
void solve()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
ll ans=0;
int flag;
if(a[1]>0)
flag=1;
else flag=-1;
int temp=-inf;
for(int i=1;i<=n;i++)
{
	if(flag==1&&a[i]<0)
	{
		ans+=temp;
		temp=-inf;
		flag=-1;
	}
	else if(flag==-1&&a[i]>0)
	{
		ans+=temp;
		temp=-inf;
		flag=1;
	}
	temp=max(temp,a[i]);
}
ans+=temp;
printf("%lld\n",ans);
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

D - Constant Palindrome Sum

题目大意:给你一个数组,每个元素范围在 [ 1 , k ] [1,k] [1,k]。你每一次操作可以改变一个数,但范围仍旧是 [ 1 , k ] [1,k] [1,k]。问你最少需要改变几次可以把最终数组变成对应的回文相加值始终相等(这里可能表达的不清楚,具体去看一下原题)。

题解:因为范围是 [ 1 , k ] [1,k] [1,k],两个元素的和的范围也就是 [ 2 , 2 k ] [2,2k] [2,2k],我们需要一对对的来看,改变次数分为0,1,2三种情况。(具体看代码吧,我表达不清楚了,逃)

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
 
int a[maxn],cnt[2*maxn],b[2*maxn];
void solve()
{
int n,k,p=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=2;i<=k*2;i++){
cnt[i]=n;
b[i]=0;
}
for(int i=1;i<=n/2;i++)
{
	b[min(a[i],a[n+1-i])+1]--;
	b[max(a[i],a[n+1-i])+k+1]++;
	cnt[a[i]+a[n+1-i]]--;
}
int ans=inf;
for(int i=2;i<=2*k;i++)
{
    if(b[i]) p+=b[i];
    cnt[i]+=p;
	ans=min(ans,cnt[i]);
}
printf("%d\n",ans);
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

有什么意见或建议的话可以写在评论区,觉得对你有帮助的话欢迎点赞。

你可能感兴趣的:(算法)