SCPC-续写神犇的传说(组合数学,逆元)

题目链接

题意:

给你一个数组,从中任意拿出一部分数字,求和为偶数的情况有多少种。

思路:

首先求出有多少个奇数多少个偶数,如果想让和为偶数,那么奇数一定要有偶数个,而偶数则没有要求,这里就用到了组合数学,偶数个是挂件,我们只需要求出每个偶数个的奇数有多少种再乘上偶数的所有排列即可,最后的结果对1e9+7取模。

知识点:

因为要用到组合数学,数据很大,要在中间取模,而中间取模后再乘就有可能导致出现小数从而影响结果,所以要用到逆元思想。除以一个数对mod取模就相当于乘上这个数的mod-2次方再对mod取模。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e6+7;
const int mod=1e9+7;
const int inf=0x7fffffff;
const double pi=3.1415926535;
int n,sum0=0,sum1=0,sum=1,num=0,arr[N];
int quick(int a,int n)
{
    if(n==0)
    {
        return 1;
    }
    int x=quick(a,n/2),ans=x*x%mod;
    if(n%2==1)
    {
        ans=ans*a%mod;
    }
    return ans;
}
signed main()
{
    IOS;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int a;
        cin>>a;
        if(a%2==0)
        {
            sum0++;
        }
        else
        {
            sum1++;
        }
    }
    sum0=quick(2,sum0);
    num+=sum0-1;
    arr[0]=1;arr[1]=1;
    for(int i=1;i<=sum1;i++)
    {
        arr[i]=arr[i-1]*i%mod;
    }
    for(int i=2;i<=sum1;i+=2)
    {
        num=(num+(arr[sum1]*quick(arr[i],mod-2)%mod)*quick(arr[sum1-i],mod-2)%mod*sum0)%mod;
    }
    cout<<num<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ACkingdom/article/details/106750494
今日推荐