A. Balloons
题目链接:http://codeforces.com/contest/998/problem/A
题目大意:让你把所有的气球分成两份,使得两份的数量不同,随便分。
解题思路:用一个结构体存数量和序号,在根据数量排个序,对于n<=2进行特判下,对于n>2的情况直接输出1和第一个数的序号即可。
AC代码:
struct node
{
int x;
int id;
}e[15];
bool cmp(node a, node b)
{
return a.x < b.x;
}
int main()
{
int n, a[20];
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i ++) {
scanf("%d", &e[i].x);
e[i].id = i+1;
}
sort(e, e+n, cmp);
if(n <= 1) {
printf("-1\n");
continue;
}
if(n == 2) {
if(e[0].x == e[1].x) printf("-1\n");
else printf("1\n1\n");
continue;
}
printf("1\n%d\n", e[0].id);
}
return 0;
}
题目链接:http://codeforces.com/contest/998/problem/B
题目大意:给你一个数组,让你把他分成几块,使得每块的奇数个数和偶数个数相同,每次分的花费为分开处两边数字差的绝对值,让你求出在花费不超过B的情况下,能分几下。
解题思路:先求出奇数和偶数个数的前缀和,然后按照前缀和的个数把所有能分的地方的花费都算出来,再排个序,从小到大取,直到大于B,最后输出次数。
AC代码:
int main()
{
int n, b, a[110], sum1[110], sum2[110];
while(~scanf("%d%d", &n, &b)) {
mem0(sum1);
mem0(sum2);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
if(a[i]&1) {
sum1[i] = sum1[i-1] + 1;
sum2[i] = sum2[i-1];
}else {
sum1[i] = sum1[i-1];
sum2[i] = sum2[i-1] + 1;
}
}
int cost[110], sum = 0;
for(int i = 1; i < n; i ++) {
if(sum1[i] == sum2[i] && sum1[n] - sum1[i] == sum2[n] - sum2[i]) {
cost[sum ++] = abs(a[i] - a[i+1]);
}
}
sort(cost, cost+sum);
int ans = 0, s = 0;
for(int i = 0; i < sum; i ++) {
s += cost[i];
if(s <= b) {
ans ++;
}else break;
}
printf("%d\n", ans);
}
return 0;
}
题目链接:http://codeforces.com/contest/998/problem/C
题目大意:给你一个字符串,有两种操作,花费x把一段字符串反转,花费y把一段连续的0都变成1,求出把该字符串全都变成1的最小花费。
解题思路:先求出0块区域的数量为sum,如果没有反转的操作,那么就需要进行sum次变换的操作,有了反转这个操作,模拟下你会发现,每一次反转操作都只会减少一个0块,所以就相当与一次反转操作可以代替一次变换的操作,这样这个问题就成了一个贪心的问题:当x<y时,就尽量多进行反转,也就是反转sum-1次,最后进行一次变换的操作即可,如果x>=y时,就都进行变换的操作。
AC代码:
int main()
{
int n;
LL x, y;
char str[300010];
while(~scanf("%d%lld%lld", &n, &x, &y)) {
scanf("%s", str);
LL sum = 0;
for(int i = 0; i < n-1; i ++) {
if(str[i] == '0' && str[i+1] == '1') sum ++;
}
if(str[n-1] == '0') sum ++;
if(sum == 0) printf("0\n");
else if(y <= x) {
printf("%I64d\n", sum*y);
}else {
printf("%I64d\n",x*(sum-1) + y);
}
}
return 0;
}
题目链接:http://codeforces.com/contest/998/problem/D
题目大意:给你4个数1 5 10 50,让你挑n个数相加,每个数可以选任意次数,求出能算出多少种不同的数字。
解题思路:%彪神一波,思路数彪神给的:对于这种类型的题,一看数据范围这么大,然后又没有取模的操作,对于每个样例又是出入输出的类型,那么肯定是打表找规律的题,或者可能是什么结论或着公式题之类的,也许这就是题目做多了后,自然又得题感吧,看来还是要多刷题啊!切入正题,我们先dfs跑一边结果,看看有没有什么联系,果然在n<=11时并没有什么联系,但是当n>12时,结果就是一个公差为49的等差数列,那么我们对n<=11的结果进行打表,后面的不断加49即可。
AC代码:
LL a[12] = {
4,
10,
20,
35,
56,
83,
116,
155,
198,
244,
292
};
int main()
{
LL n;
while(~scanf("%I64d", &n)) {
if(n <= 11) {
printf("%I64d\n", a[n-1]);
}else {
printf("%I64d\n", a[10] + 49*(n-11));
}
}
return 0;
}