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;
}