http://codeforces.com/contest/798/problem/D
题目大意:
给你两个数组长度为n的数组a,b,让你从中选择n/2+1个下表,使得对于每个数组,选择的元素之和的二倍大于整个数组的元素之和。
解题思路:
首先,对于题目要求的选择元素之和两倍大与所有元素之和,我们可以转化为选择元素之和大于剩下的。然后我们可以将下标按照a从大到小排序。然后选择第一个,之后每两个一组,选择b大的一个,如果n是偶数再选择最后一个。
至于这样写的正确性:首先对于数组b,每一组选择的都是大的,而且还有多选的,所以一定比剩下的大。对于数组a,从第一个开始看,当前选择的,一定比下一组剩下的a大。所以这样贪心就一定正确。
总结一下就是,对于二维的贪心我们可以先让它变成其中一维有序,这样只需要重点考虑另一维,就会简单很多。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100000 + 10;
int a[maxn];
int b[maxn];
int n;
int p[maxn];
bool cmp(const int &x, const int & y)
{
return a[x] > a[y];
}
int main()
{
while (scanf("%d", &n) != EOF)
{
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
{
scanf("%d", &b[i]);
}
for (int i = 1; i <= n; i++)
p[i] = i;
sort(p + 1, p + n + 1, cmp);
printf("%d\n", n / 2 + 1);
printf("%d", p[1]);
for (int i = 2; i < n; i += 2)
{
int x = p[i], y = p[i + 1];
if (b[x] > b[y])
printf(" %d", x);
else printf(" %d", y);
}
if (n % 2 == 0)
printf(" %d", p[n]);
cout << endl;
}
return 0;
}
http://codeforces.com/contest/798/problem/C
转载自:
题意】
给你n个数字;
要求你进行若干次操作;
每次操作对第i和第i+1个位置的数字进行;
将
a[i]变为a[i]-a[i+1],a[i+1]变为a[i]+a[i+1];
然后问你能不能通过以上变换使得最后所有元素的gcd>1
【题解】
答案总是存在的;
因为把这个操作进行两次可以得到-2*a[i+1],2*a[i]
也就是如果对每相邻的元素进行操作,最后都能使得这两个元素都变成偶数;
最后gcd最少都为2了;
则:
如果一开始所有元素的gcd>1则直接输出0;
等于1;
假设改变一次后的gcd为d
则d|a[1..i-1]且d|a[i+2..n]
且d|a[i]-a[i+1]且d|a[i]+a[i+1]
因为由d|x和d|y可以得到
d|x+y以及d|x-y
所以
d|2*a[i]且d|2*a[i+1]
这样就大概猜测要使得每个元素都变成偶数吧.
每个元素都贪心地让他变成偶数就好了;
(有了“这个操作进行两次可以得到-2*a[i+1],2*a[i]”这个结论,我们可以放心地进行贪心,当然不一定是都要进行两次操作,比如a[i]和a[i+1]都是奇数,则只要进行一次操作,因为一次操作后两个数的奇偶性都会因为加、减了一个奇数而发生改变);
只要第i个元素没有变成偶数就一直进行这个操作;
然后第n个元素如果最后在前n-1个元素进行操作之后没有变成偶数;
则必然可以对n-1,n操作两次使得a[n-1]保留仍旧是偶数,a[n]也变成了偶数;
因为
a[n-1]是偶数了,a[n]是奇数
第一次操作后
a[n-1]变成奇数,a[n]还是奇数;
再进行一次操作后
a[n-1]变成偶数,a[n]也变成偶数;
具体看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100000 + 10;
typedef long long ll;
int a[maxn];
int gcd(int x, int y)
{
return y ? gcd(y, x%y) : x;
}
int n;
int main()
{
while (~scanf("%d", &n))
{
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int c = a[1];
for (int i = 2; i <= n; i++)
{
c = gcd(c, a[i]);
}
puts("YES");
if (c > 1)
{
cout << 0 << endl;
continue;
}
int ans = 0;
for (int i = 1; i <= n; )
{
if (a[i] % 2 == 0)
{
i++;
continue;
}
int j = i;
while (a[j] % 2 && j <= n)
{
j++;
}
if ((j - i) % 2 == 0)
ans += (j - i) / 2;
else ans += (j - i) / 2 + 2;
i = j;
}
cout << ans << endl;
}
return 0;
}