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