AcWing 1875. 贝茜的报复

·  阅读 933

目录:算法日记

题目来源:1875. 贝茜的报复 - AcWing题库

题目描述

农夫约翰和奶牛贝茜喜欢在业余时间互相出数学题。

约翰给贝茜出了一道相当难的问题,导致她没能解决。

现在,她希望通过给约翰出一道有挑战性的难题来报复他。

贝茜给了约翰一个表达式 (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,MB,E,S,I,G,O,M

对于每个变量,她给约翰一个列表,表中包含该变量可采用的最多 2020 个整数值。

她要求约翰计算,共有多少种给变量赋值的方法可以使得表达式的计算结果为偶数。

输入格式

第一行包含一个整数 NN

接下来 NN 行,每行包含一个变量和该变量的一个可能值。

每个变量至少出现 11 次,最多出现 2020 次。

同一变量不会重复列出同一可能值。

输出格式

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

数据范围

  • 7N1407≤N≤140
  • 所有变量的可能取值范围 [300,300][−300,300]
  • 本题答案不会超出int范围。

算法思路

题目要求计算共有多少种给变量赋值的方法可以使得表达式(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)的计算结果为偶数,先考虑暴力计算每种可能是否可解。题目中共给出了77个变量,每个变量最多可以采用2020个整数的值,因此所有的可能的情况共有20720^7种。考虑优化。

注意仅统计(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)为偶数的计算结果,求偶数等价于除以22的余数等于00对于乘法、加法和减法,取余运算有分配律,即每个变量的值直接对22取余,仅存在010,1两种情况,对应所有可能的情况减少到272^7种,这样处理之后可以暴力求解。

77个变量使用77位二进制位数表示,枚举每种结果为偶数的组合,根据乘法原理,计算合法赋值方式的组合。由于相同的两个数相加一定是偶数,可利用这个性质简化判断条件。

AC代码

#include<iostream>
#include<map>
using namespace std;
map<char, int> cnt[2];
int n;
int main() {
    cin>>n;
    for(int i = 0; i < n; ++i) {
        char c;
        int x;
        cin>>c>>x;
        cnt[abs(x % 2)][c]++;
    }
    char str[] = "BESIGOM";
    int res = 0;
    //枚举每种可能
    for(int i = 0; i < 1 << 7; ++i) {
        map<char, int> v;
        // 取出每一位
        for(int j = 0; j < 7; ++j) {
            v[str[j]] = i >> j & 1;
        }
        // 判断合法方案数量,if成立说明当前枚举到的状态合法
        if((v['B'] + v['I']) * (v['G'] + v['O'] + v['E'] + v['S']) * v['M'] % 2 == 0) {
            int sum = 1;
            for(int j = 0; j < 7; ++j) {
                sum *= cnt[v[str[j]]][str[j]];
            }
            res += sum;
        }
    }
    cout<<res<<endl;
    return 0;
}
复制代码
分类:
代码人生
标签:
分类:
代码人生
标签:
收藏成功!
已添加到「」, 点击更改