Codeforces Round #717 (Div. 2)-C. Baby Ehab Partitions Again-题解

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #717 (Div. 2)-C. Baby Ehab Partitions Again-题解相关的知识,希望对你有一定的参考价值。

Codeforces Round #717 (Div. 2)-C. Baby Ehab Partitions Again

传送门
Time Limit: 2 seconds
Memory Limit: 256 megabytes

Problem Description

Baby Ehab was toying around with arrays. He has an array a a a of length n n n. He defines an array to be good if there’s no way to partition it into 2 2 2 subsequences such that the sum of the elements in the first is equal to the sum of the elements in the second. Now he wants to remove the minimum number of elements in a a a so that it becomes a good array. Can you help him?

A sequence b b b is a subsequence of an array a a a if b b b can be obtained from a a a by deleting some (possibly zero or all) elements. A partitioning of an array is a way to divide it into 2 2 2 subsequences such that every element belongs to exactly one subsequence, so you must use all the elements, and you can’t share any elements.

Input

The first line contains an integer n n n ( 2 ≤ n ≤ 100 2 \\le n \\le 100 2n100) — the length of the array a a a.

The second line contains n n n integers a 1 a_1 a1, a 2 a_2 a2, … \\ldots , a n a_{n} an ( 1 ≤ a i ≤ 2000 1 \\le a_i \\le 2000 1ai2000) — the elements of the array a a a.

Output

The first line should contain the minimum number of elements you need to remove.

The second line should contain the indices of the elements you’re removing, separated by spaces.

We can show that an answer always exists. If there are multiple solutions, you can print any.

Sample Input

4
6 3 9 12

Sample Onput

1
2

Note

In the first example, you can partition the array into [ 6 , 9 ] [6,9] [6,9] and [ 3 , 12 ] [3,12] [3,12], so you must remove at least 1 1 1 element. Removing 3 3 3 is sufficient.

In the second example, the array is already good, so you don’t need to remove any elements.


题目大意

给你 n n n个数,让你去掉尽可能少的数,使得剩下的数不能被分成和相等的两份。
和相等的两份是指第一份中的所有的元素的和等于第二份中所有的元素的和。


输出描述

这一题保证必定有解。

第一行输出至少需要去除的数的个数
第二行输出要去除的这些数的下标。


解题思路

这题答案只能是 0 0 0 1 1 1

  • 如果本来就不能分成两份,那么只需要去除 0 0 0个数,即答案是 0 0 0
  • 如果本来能够分成和相等的两份,那么就说明这些数的和是偶数(这些数的和是奇数的话,是不可能分成和相等的两组的)。然后就看这些数中有没有一个奇数。
    • 如果这些数中包含奇数,我们只需要把这一个奇数去掉,剩下的数的和就变成了奇数,就不能分成和相等的两组。
    • 否则这些数中都是偶数的话,就所有数分别除以 2 2 2,不影响分配结果(如果除以 2 2 2之前能分成和相等的两组的话,那么都除以 2 2 2之后他们的和还相等)。直到含有奇数为止,就去掉这个奇数,即为答案。

那么问题就是如何快速确定最初的数组能不能分成连个和相同的数组,用01背包即可解决。

我们用一个 b o o l bool bool类型的数组 d p [ i ] [ j ] dp[i][j] dp[i][j]来表示前 i i i个数的和能不能是 j j j
那么当前 i − 1 i-1 i1个数的和能为 j j j时,就不加上这个(第 i i i个)数,和还是 j j j
或者前 i − 1 i-1 i1个数的和正好能组成 j − 这 个 ( 第 j-这个(第 ji 个 ) 数 的 值 个)数的值 ,那么加上这个数,总和正好是 j j j
状态转移方程:dp[i][j]=dp[i-1][j]|dp[i-1][j-a[i]]


AC代码

#include <bits/stdc++.h>
using namespace std;
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int a[111]={0};
bool dp[111][111111]={0};//dp[i][j]表示前i个能不能正好为j
int main()
{
    int n;
    cin>>n;
    int sum=0;//sum代表这n个数的总和
    fi(i,0,n)//for(int i=0;i<n;i++)
        cd(a[i]),sum+=a[i];//scanf("%d", &a[i]),sum+=a[i]
    if(sum%2)//如果总和是奇数,直接就不能分成和相等的两组,去掉0个数即可
    {
        puts("0");
        return 0;
    }
    sum/=2;//否则要找这n个数中,能不能找到一些数,他们的和是sum/2。如果能找到,就说明可以分成相等的两组
    for(int i=0;i<n;i++)//初始化dp数组
    {
        dp[0][a[i]]=1;
    }
    for(int i=1;i<=n;i++)//前i个数
    {
        for(int j=sum;j>=a[i];j--)//和能不能是j
        {
            dp[i][j]=dp[i-1][j]|dp[i-1][j-a[i]];
        }
    }
    if(!dp[n][sum])//如果原本的数就不能分成和相等的2份
    {
        puts("0");//直接去掉0个元素即可
        return 0;
    }
    puts("1");//否则需要去掉一个元素
    while(1)
    {
        fi(i,0,n)//for(int i=0;i<n;i++)
        {
            if(a[i]%2)//找到了一个奇数
            {
                printf("%d\\n",i+1);//去掉这个奇数,剩下的数的和就是奇数,就不能分成两组了
                return 0;
            }
        }
        fi(i,0,n)//全部除以2
        {
            a[i]/=2;
        }
    }
    return 0;
}

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/116355141

以上是关于Codeforces Round #717 (Div. 2)-C. Baby Ehab Partitions Again-题解的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #717 (Div. 2)-A. Tit for Tat-题解

区间倍增dpD. Cut——Codeforces Round #717 (Div. 2)

Codeforces Round #717 (Div. 2)-C. Baby Ehab Partitions Again-题解

Codeforces Round #717 (Div. 2)-B. Maximum Cost Deletion-题解

Codeforces Round #717 (Div. 2)-B. Maximum Cost Deletion-题解

Codeforces Round #717 (Div. 2)-C. Baby Ehab Partitions Again-题解