解题思路:

要求分割两个子集,其中一个可以为空集,且两个集合为偶数,所有第一步判断集合的总和是否为偶数,如果不为偶数则直接判定为 0 个否则再进行深度收搜判断 (暴力超时)

也可以利用奇数个数与偶数个数的排列组合实现, 将两个奇数拼接为一个偶数,判断无重复的奇数拼接情况,与偶数个数相加,递推排列组合公式  (正解)

优化排列组合,会发现是高精度算法 设 x 为偶数个数, y 为奇数个数ans = pow(x + (y == 0 ? 0 : y - 1)) % mod 算法标签:递推,找规律,贪心


注意事项:
 x + (y == 0 ? 0 : y - 1), 奇数为0情况

```

参考代码:

//排列组合递推公式

import java.util.Scanner;
import java.math.BigInteger;
public class Main {
    public static final BigInteger MOD = new BigInteger("1000000007");
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int T = scan.nextInt();
        while (T-- > 0){
            int n = scan.nextInt();
            int[] a = new int[n];
            long x = 0, y = 0; // x 记录偶数, y 记录奇数
            for(int i = 0; i < n; i++){
                a[i] = scan.nextInt() % 2;
                if(a[i] == 0){
                    x++;
                }else {
                    y++;
                }
            }
            if(y % 2 == 1){ // 奇数个数为奇,没有一个条件成立
                System.out.println(0);
                continue;
            }
            x = x + (y == 0 ? 0 : y - 1);  // 两个奇数组合为一个偶数,排除重复情况
            BigInteger ans = new BigInteger("2");
            BigInteger dp = new BigInteger("1");
            // C(n,m) = P(n,m) / P(m,m) = n! / m! * (n - m)!
            // 转移递推公式 dp = (dp * (x, x-1, x-2, ... , n) / (1, 2, 3, ... , n))
            for(long i = 1, j = x; i < x; i++, j--){ // 排列组合无顺序 C
                BigInteger u = new BigInteger(String.valueOf(j));
                BigInteger v = new BigInteger(String.valueOf(i));
                dp = dp.multiply(u).divide(v);
                ans = ans.add(dp);
            }
            System.out.println(ans.mod(MOD));
        }
    }
}







//优化高精度

import java.util.Scanner;
import java.math.BigInteger;
public class Main {
    public static final BigInteger MOD = new BigInteger("1000000007");
    public static final BigInteger TWO = new BigInteger("2");
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int T = scan.nextInt();
        while (T-- > 0) {
            int n = scan.nextInt();
            int x = 0, y = 0; // x 记录偶数, y 记录奇数
            for (int i = 0; i < n; i++) {
                int a = scan.nextInt() % 2;
                if (a == 0) {
                    x++;
                } else {
                    y++;
                }
            }
            if (y % 2 == 1) {
                System.out.println(0);
            }else{
                System.out.println(TWO.pow(x + (y == 0 ? 0 : y - 1)).mod(MOD));
            }
        }
    }
}
点赞(0)
 

0.0分

4 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 3 条评论

dotcpp0713563 1年前 回复TA
@哈哈哈 排列Cx从1到x的和,可以理解为第一次是从x个中拿1个,第二次第三次一次递推,然后将这些排列相加就行
刘飞061 1年前 回复TA
@哈哈哈 找出来的规律
哈哈哈 1年前 回复TA
看不懂,递推公式怎么来的