农夫约翰和奶牛贝茜喜欢在业余时间互相出数学题。
约翰给贝茜出了一道相当难的问题,导致她没能解决。
现在,她希望通过给约翰出一道有挑战性的难题来报复他。
贝茜给了约翰一个表达式 (B+E+S+S+I+E)(G+O+E+S)(M+O+O),其中包含七个变量 B,E,S,I,G,O,M(O 是变量,不是零)。
对于每个变量,她给约翰一个列表,表中包含该变量可采用的最多 20 个整数值。
她要求约翰计算,共有多少种给变量赋值的方法可以使得表达式的计算结果为偶数。
第一行包含一个整数 N。
接下来 N 行,每行包含一个变量和该变量的一个可能值。
每个变量至少出现 1 次,最多出现 20 次。
同一变量不会重复列出同一可能值。
输出可以使得表达式的计算结果是偶数的给变量赋值的方法总数。
7≤N≤140,
所有变量的可能取值范围 [−300,300]
本题答案不会超出int范围。
10
B 2
E 5
S 7
I 10
O 16
M 19
B 3
G 1
I 9
M 2
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
可以将公式简化为(B+I)*(G+O+E+S)*(M),判断这个式子的奇偶性。
搜先可以想到暴力求解,也就是枚举每个字母的取值情况,这样每个字母最多可以取20个数,
7个字母的话时间复杂度就是O(20^7),TLE是肯定的。
这里有一个简化就是,判断这7个字母是奇数还是偶数,这样每个字母的取值不是偶数就是奇数,就只有有两种情况。
遍历所有情况可以分为两个流派:
DFS流派:优点是时间复杂度低O(2^n),缺点是代码长。
二进制流派:优点是代码短,缺点是时间复杂度较高O(n*n^n)。
对于这个题,不论是什么流派,做题步骤就是:
记录每一个字母的奇数,偶数的个数
枚举每一个字母的奇数和偶数的情况(2^7种情况)
满足 B + I,或者 G + O + E + S 或者 M 其中一个为偶数,则答案为偶数
假如满足,累加到答案res中
#include
using namespace std;
int n;
unordered_mapcnt[2];
char str[]="BESIGOM";
int res=0;
unordered_mapv;
void dfs(int u,int x) {
if(u==7) {
if ((v['B'] + v['I']) * (v['G'] + v['O'] + v['E'] + v['S']) * v['M'] % 2 == 0) {
res+=x;
}
return;
}
char c=str[u];
// cout<>n;
while(n--) {
char c;
int x;
cin>>c>>x;
cnt[abs(x)%2][c]++;
}
//开始枚举每个字符的奇偶情况
dfs(0,1);//当前枚举到那个字母了,当前的取值情况的方案数
cout<
#include
#define int long long
using namespace std;
const int N = 1e5+10;
signed main() {
int n;
cin>>n;
unordered_mapcnt[2];
while(n--) {
char c;
int x;
cin>>c>>x;
cnt[abs(x)%2][c]++;
}
char str[]="BESIGOM";
int res=0;
unordered_mapv;
//开始枚举每个字符的奇偶情况
for(int i=0; i<1<<7; i++) {
for(int j=0; j<7; j++) {
v[str[j]]=i>>j&1;
}
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[i>>j&1][str[j]];
}
res+=sum;
}
}
cout<