小红拿到了一个长度为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);
}
}