【算法题】所有和为奇数子序列之和

小红拿到了一个长度为n的数组。她定义一个子序列是“好的”,当且仅当该子序列所有元素之和为奇数。现在小红想求出所有“好的”子序列的元素和之和。你能帮帮她吗?由于答案可能过大,请对10^9+ 7取模。定义一个数组的子序列是,数组中取若干元素(可以不连续)按原数组顺序形成的新数组。

输入描述
第一行输入一个正整数n,代表小红拿到的数组。
第二行输入几个正整数 a i a_i ai,代表数组中的元素。
输出描述
所有“好的”子序列的元素和之和,答案对10^9+ 7取模。

示例
输入

3
1 3 2

输出

12

说明
好的子序列有以下几个:
[1],[3],[1,2],[3,2],答案是1+3+3+5=12

思路:选择其中奇数个奇数,然后选择任意个偶数,都能形成好序列。所以将每个数乘以它在所有子序列中出现的次数,并求和即可。

  • 对于奇数来说,出现次数是在奇数集合里出现的次数,乘以偶数集合的所有子集数
  • 对于偶数来说,出现次数是在偶数集合里出现的次数,乘以奇数集合的所有奇数个子集数

Java代码:未经验证

public class Test {
    
    
    static final int MOD = 1000000007;

    public static void main(String[] args) {
    
    
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] a = new int[n];
        int odd_num = 0, even_num = 0;
        for (int i = 0; i < n; i++) {
    
    
            a[i] = in.nextInt();
        }
        for (int i = 0; i < n; i++) {
    
    
            if (a[i] % 2 == 0) {
    
    
                even_num++;
            } else {
    
    
                odd_num++;
            }
        }
        long res = 0;
        if (odd_num == 0) {
    
    
            System.out.println(0);
            return;
        }
        // each_odd * each_odd_appear_times * even_choices
        // each_even * each_even_appear_times * odd_choices
        double pow = odd_num > 1 ? Math.pow(2, odd_num - 2) : 1;
        long odd_param = (long) (pow * Math.pow(2, even_num) % MOD);
        long even_param = (long) (Math.pow(2, even_num - 1) * Math.pow(2, odd_num - 1) % MOD);
        for (int i = 0; i < n; i++) {
    
    
            if (a[i] % 2 == 0) {
    
    
                res += even_param * a[i] % MOD;
            } else {
    
    
                res += odd_param * a[i] % MOD;
            }
        }
        System.out.println(res % MOD);

    }
}

猜你喜欢

转载自blog.csdn.net/bthbt/article/details/138252642