数组分割蓝桥杯java b组

文章讨论了一道编程题,涉及数组中奇数和偶数的加法规则。题解指出,当数组总和为偶数时,可以将数组分为两个偶数和的子集。通过奇偶性分析,得出只需从偶数子集中选择和从奇数子集中选择偶数个元素,即可保证子集和为偶数。文章提供了快速幂算法计算符合条件的子集组合数。
摘要由CSDN通过智能技术生成

一题解:

阅读前必备知识点:奇数加减奇数为偶数,偶数加减偶数为偶数,奇数加减偶数为奇数

由题意可知S1+S2=sum(sum是整个A数组的和),且知道S1和S2是偶数,根据数学性质偶数相加减偶数还是得到偶数

 

可知sum为奇数必定无解结果为0,所以sum必须为偶数。

接下来根据上面的推导也不难得出一个结论:当sum为偶数,S1为偶数,S2一定为偶数。

所以在sum为偶数的情况下我们只需要确保S1是偶数即可。

根据阅读前必备知识点得出:1.A数组里任意的偶数子集相加必定也为偶数,2。偶数个奇数相加为偶数,所以从A数组中的奇数子集中任选偶数个,就能保证选出的奇数子集相加也为偶数.,由1和2得出:只需要从A数组任意偶数子集中选和A数组中奇数子集中任选偶数个组合在一起就能枚举所有符合S1是偶数的情况。

接下来让我们推导公式计算有多少符合条件的情况:首先设so为A的偶数集合,sj为A的奇数集合,so的长度为r,sj的长度为l,首先我们从so中任取一个集合,so里面每个数可选和不选,利用分布积分法计算可得。

接下来推导sj有多少个子集:首先给出结论,l必须为偶数,为了确保s1和s2为偶数,和S1必须只能包含偶数个的奇数,S2也必须包含偶数个的奇数,所以l=R1里的奇数个数+R2里的奇数个数,偶数加减偶数任然为偶数,则l为偶数。

 

 由于推导过于困难,并且考虑在考场时间紧迫,不如按照规律大胆推测

我们可以根据规律得出:sj的集合数=2^l-1

最终S1的选择方法数=(2^r)*(2^(r-1))(分布积分法)

二,代码:

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <unordered_map>
#include <string>
using namespace std;
using ll = long long;
const ll mod = 1000000007;
ll f(ll a, ll n) //快速幂
{
    if (n < 0) return 1;
    ll res = 1;
    while (n) 
    {
        if (n%2!=0) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res % mod;
}
int main() {
    ll t;
    cin >> t;
    while (t--)
    {
        ll n;
        cin >> n;
        ll r = 0, l = 0;//r=偶数个数,l=奇数个数
        ll sum = 0;
        for (int i = 1; i <= n; i++)
        {
            ll temp;
            cin >> temp;
            sum += temp;
            if (temp % 2 == 0)r++;
            else l++;
        }
        if (sum % 2 != 0)
        {
            cout << 0 << endl;
        }
        else
        {
            cout << f(2, r) % mod * f(2, l - 1) % mod << endl;
        }
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值