AtCoder Grand Contest 017-A Biscuits

A - Biscuits
Time limit : 2sec / Memory limit : 256MB
Score : 200 points

Problem Statement

There are N bags of biscuits. The i-th bag contains Ai biscuits.

Takaki will select some of these bags and eat all of the biscuits inside. Here, it is also possible to select all or none of the bags.

He would like to select bags so that the total number of biscuits inside is congruent to P modulo 2. How many such ways to select bags there are?

Constraints
1≤N≤50
P=0 or 1
1≤Ai≤100

Input
Input is given from Standard Input in the following format:
N P
A1 A2 … AN

Output
Print the number of ways to select bags so that the total number of biscuits inside is congruent to P modulo 2.

Sample Input 1
2 0
1 3

Sample Output 1
2

There are two ways to select bags so that the total number of biscuits inside is congruent to 0 modulo 2:

Select neither bag. The total number of biscuits is 0.
Select both bags. The total number of biscuits is 4.

Sample Input 2
1 1
50

Sample Output 2
0

Sample Input 3
3 0
1 1 1

Sample Output 3
4

Two bags are distinguished even if they contain the same number of biscuits.

Sample Input 4
45 1
17 55 85 55 74 20 90 67 40 70 39 89 91 50 16 24 14 43 24 66 25 9 89 71 41 16 53 13 61 15 85 72 62 67 42 26 36 66 4 87 59 91 4 25 26

Sample Output 4
17592186044416

吃个饼干怎么这么矫情

题解

题意

这道题目说白了就是
给你n个数,求在这n个数当中任取任意个数(包括0个)之和mod 2等于P的情况的个数

据说有两种解法,一种是动归,一种是组合数

反正我用的是动归

方程

我们定状态JI[i]表示到第i个数为止,共有多少种奇数组合
OU[i]表示到第i个数为止,共有多少种偶数组合

显然有OU[0]=1,JI[0]=0

那么,当第i个数为奇数时
求JI[i]:
    OU[i-1]当中的所有组合加上它都是奇数
    同时JI[i-1]当中的所有组合依旧不变
    所以JI[i]=JI[i-1]+OU[i-1]

    此处注意,虽然第i个数也是奇数,但是由于偶数组合当中存在了0,0加上它即为它本身,所以我们不需要单独加一个情况

求OU[i]:
    OU[i-1]当中的所有组合不变
    JI[i-1]当中的所有组合加上它都是偶数
    所以OU[i]=JI[i-1]+OU[i-1]

当第i个数为偶数时
求JI[i]:
    JI[i-1]当中所有组合不变的同时,所有组合加上它都是奇数
    所以JI[i]=JI[i-1]*2
求OU[i]:
    OU[i-1]当中所有组合不变的同时,所有组合加上它都是偶数
    所以OU[i]=OU[i-1]*2
    此处注意同上,由于存在了0,加上它之后为它本身,所以无需再单独增加一个情况

因此得到方程:

num[i]&1==1:(num[i]为奇数)
    JI[i]=OU[i]=JI[i-1]+OU[i-1]

num[i]&1==0:(num[i]为偶数)
    JI[i]=JI[i-1]<<1;
    OU[i]=OU[i-1]<<1;

注意

此处的结果JI[i]和OU[i]都只与JI[i-1]和OU[i-1]有关,因此可以用类似于滚动数组的优化方式,只用两个变量即可算出变量

附上代码

#include <iostream>
#include <cstdio>
using namespace std;

int n,p,a;
long long J=0,O=1;

int main()
{
    freopen("In.txt","r",stdin);
    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a);
        if(a&1)
        {
            O=J+O;
            J=O;
        }
        else
        {
            J=J<<1;
            O=O<<1;
        }
    }
    if(p)cout<<J;
    else cout<<O;
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值