D - Logical Expression

题目来源: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;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页