题目来源:https://atcoder.jp/
一、题目大意
给定N个字符串S1 ,…,Sn ,每个字符串内容为 AND 或 OR 。找到使yn为1的序列(x0 ,…,xn)的数量。
1.y0 = x0
2.对于i >= 1 ,当Si 为AND时,yi =y i-1 ∧xi ;当Si 为OR时,yi =y i-1 ∨xi
二、输入
第一行,一个正整数 N 。
后面N行为S1 …Sn
三、输出
满足条件的序列数量
四、样例
样例一
input:
2
AND
OR
output:
5
样例二
input:
5
OR
OR
OR
OR
OR
output:
63
五、代码+思路
方法一 动态规划
参考大佬:https://www.cnblogs.com/HotPants/p/14320191.html
定义状态f[i][j] 表示yi 为 j 的方案数量
入口:f[0][0] = 1 , f[0][1] = 1
状态转移:
若第i个操作为AND,若要使yi 为0:xi为1,yi-1为0,或者xi为0,yi任意。
若第i个操作为AND,若要使yi 为1:xi为1,yi-1为1。
f[i][0] = f[i - 1][0] + (f[i - 1][0] + f[i - 1][1])
f[i][1] = f[i - 1][1]
若第i个操作为OR,若要使yi 为0:xi为0,yi-1为0。
若第i个操作为OR,若要使yi 为1:xi为1,yi-1任意,xi 为0,yi-1 为1
f[i][0] = f[i - 1][0]
f[i][1] =(f[i - 1][1] + f[i - 1][0]) + f[i - 1][1]
出口:f[n][1]
#include<iostream>
typedef long long ll;
using namespace std;
int main() {
ll f[64][2];
for (int i = 0; i < 64; i++)
f[i][0] = 0, f[i][1] = 0;
f[0][0] = 1, f[0][1] = 1;
int n;
cin >> n;
string op;
for (int i = 1; i <= n; i++) {
cin >> op;
if (op == "AND") {
f[i][0] = f[i - 1][0] + f[i - 1][1] + f[i - 1][0];
f[i][1] = f[i - 1][1];
}
else {
f[i][0] = f[i - 1][0];
f[i][1] = f[i - 1][0] + f[i - 1][1] + f[i - 1][1];
}
}
cout << f[n][1] << endl;
return 0;
}
方法二 位运算
y0 = x0
y1 = y0op1x1 = x0op1x1
y2 = y1op2x2 = x0op1x1op2x2
…
综上
yn = x0op1x1op2x2…xn-1opnxn
要使yn=1,只需让n+1个x相运算为1.
假设已经有了n个x组成的序列,这时候输入了opn,如果opn是AND,也就是说整个运算的最后一步是与运算,所以最后一位就必须是1,总方案数没有增加;如果opn是OR,也就是说运算的最后一步是或运算,那么,如果xn为0,总方案数没有增加,如果xn为1,那么前面n个x可以任取,总方案数就增加2n个。
#include<iostream>
typedef long long ll;
using namespace std;
int main() {
string str;
int n;
cin >> n;
ll res = 1;
for (int i = 1; i <= n; i++) {
cin >> str;
if (str == "OR") res += 1ll << i;
}
cout << res << endl;
return 0;
}