0
点赞
收藏
分享

微信扫一扫

AcWing 1875. 贝茜的报复(状态压缩)

有态度的萌狮子 2022-02-02 阅读 67
算法c++

【题目描述】
农夫约翰和奶牛贝茜喜欢在业余时间互相出数学题。
约翰给贝茜出了一道相当难的问题,导致她没能解决。
现在,她希望通过给约翰出一道有挑战性的难题来报复他。
贝茜给了约翰一个表达式 ( B + E + S + S + I + E ) ( G + O + E + S ) ( M + O + O ) (B+E+S+S+I+E)(G+O+E+S)(M+O+O) (B+E+S+S+I+E)(G+O+E+S)(M+O+O),其中包含七个变量 B , E , S , I , G , O , M B,E,S,I,G,O,M B,E,S,I,G,O,M O O O是变量,不是零)。
对于每个变量,她给约翰一个列表,表中包含该变量可采用的最多 20 20 20个整数值。
她要求约翰计算,共有多少种给变量赋值的方法可以使得表达式的计算结果为偶数。

【输入格式】
第一行包含一个整数 N N N
接下来 N N N行,每行包含一个变量和该变量的一个可能值。
每个变量至少出现 1 1 1次,最多出现 20 20 20次。
同一变量不会重复列出同一可能值。

【输出格式】
输出可以使得表达式的计算结果是偶数的给变量赋值的方法总数。

【数据范围】
7 ≤ N ≤ 140 7≤N≤140 7N140
所有变量的可能取值范围 [ − 300 , 300 ] [−300,300] [300,300]
本题答案不会超出 i n t int int范围。

【输入样例】

10
B 2
E 5
S 7
I 10
O 16
M 19
B 3
G 1
I 9
M 2

【输出样例】

6

【样例解释】
共有 6 6 6种可能的赋值方式:

(B,E,S,I,G,O,M) = (2, 5, 7, 10, 1, 16, 19) -> 53,244
                = (2, 5, 7, 10, 1, 16, 2 ) -> 35,496
                = (2, 5, 7, 9,  1, 16, 2 ) -> 34,510
                = (3, 5, 7, 10, 1, 16, 2 ) -> 36,482
                = (3, 5, 7, 9,  1, 16, 19) -> 53,244
                = (3, 5, 7, 9,  1, 16, 2 ) -> 35,496

注意,(2, 5, 7, 10, 1, 16, 19)(3, 5, 7, 9, 1, 16, 19),虽然计算结果相同,但是赋值方式不同,所以要分别计数。

【分析】


我们只需要判断式子最后的结果是否为偶数,因此可以将每个变量的不同取值分为两大类:奇数与偶数。分别统计每个变量取奇数的不同取值以及取偶数的不同取值的数量,然后使用一个 7 7 7位的二进制数的每一位分别表示 7 7 7种变量的取值状态,某一位为 0 0 0表示该变量取偶数,为 1 1 1表示取奇数,对于每一种状态,如果在该状态下式子的运算结果为偶数,则将每个变量在该奇偶状态下的取值的数量相乘,即为该状态下的计数结果,最后将每种状态的计数结果累加即为最终结果。


【代码】

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

int n, res;
unordered_map<char, int> cnt[2];//cnt[0][c]表示字符c为偶数的次数,1表示为奇数的次数
char s[] = "BESIGOM";

int main()
{
    cin >> n;
    while (n--)
    {
        char c; int x;
        cin >> c >> x;
        cnt[abs(x) % 2][c]++;
    }
    unordered_map<char, int> v;//v[c]表示字符c为奇数还是偶数
    for (int i = 0; i < 1 << 7; i++)//枚举所有奇偶组合状态
    {
        for (int j = 0; j < 7; j++) v[s[j]] = i >> j & 1;
        if ((v['B'] + v['I']) * (v['G'] + v['O'] + v['E'] + v['S']) * v['M'] % 2 == 0)
        {
            int t = 1;
            for (int j = 0; j < 7; j++) t *= cnt[v[s[j]]][s[j]];
            res += t;
        }
    }
    cout << res << endl;
    return 0;
}
举报

相关推荐

0 条评论