洛谷 P1310 表达式的值

题目传送门

因为看不懂题解里的做法,只好自己写了一个大模拟+DP.

对于带括号的式子,从里到外一层一层的处理括号,将其转化为一个数(即括号内可获得的方案数),这样做可以保证我们每次处理的都是一个不带括号的式子,只需考虑算式优先级即可,先算(*),然后将(*)的结果转化成数字,重新构成一个只含+的式子.

思维上比较简单,难度主要在于代码,需要考虑怎样一层层向里和向外处理括号的许多细节,还需要考虑最外面一层状态转移的多种情况,和处理完(*)后,转化只含+的式子的多种情况.

带调试版代码

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#define mod 10007

using namespace std;

int n,num = 1,p,sum,pp,ans[200001][2],fh[200001],_num = 1;
int f_ans[200001][2];
bool vis[200001],flag;
string l,l1;
struct kkk {
	int _1,_0;
};

inline kkk maxin(int deep,bool len) {
	int tot = 0,oo = 0,_tot = 0;;
	bool maxx = 0;
	map<int ,map<int ,int> > f,f_f;
	map<int ,bool> mx,fl;
	for(p;p < sum; p++) {
		if(deep != 1) {
			maxx = 0;
			if(l[p] == ')') break;;
			if(l[p] == '_' && l[p-1] == '+') {
				f[++tot][1] = 1;
				f[tot][0] = 1;
				maxx = 1;
			}
			if(l[p-1] == '*' && l[p] == '_') {
				f[++tot][1] = 1;
				f[tot][0] = 1;
				maxx = 1;
			}
			if(l[p-1] == '*') mx[++_tot] = 1;
			if(l[p-1] == '+') mx[++_tot] = 0;
			if(l[p] == '(') {
				p++;
				kkk u = maxin(deep + 1,1);
				f[++tot][1] = u._1;
				f[tot][0] = u._0;
				continue;
			}
			if(l[p-1] == '(' && l[p] == '_') {
				f[++tot][1] = 1;
				f[tot][0] = 1;
			}
		}
		else {
			maxx = 0;
			if(l[p] == ')') break;
			if(l[p-1] == '+' && l[p] == '_') {
				ans[++num][1] = 1;
				ans[num][0] = 1;
				maxx = 1;
			}
			if(l[p-1] == '*' && l[p] == '_') {
				ans[++num][1] = 1;
				ans[num][0] = 1;
				maxx = 1;
			}
			if(l[p-1] == '*') fh[++_num] = 1;
			if(l[p-1] == '+') fh[++_num] = 0;
			if(l[p] == '_' && p == 0) {
				ans[num][1] = 1;
				ans[num][0] = 1;
				flag = 1;
			}
			if(l[p] == '(') {
				p++;
				kkk u;
				u = maxin(deep + 1,1);
				ans[++num][1] = u._1;
				ans[num][0] = u._0;
				continue;
			}
		}
	}
	if(deep != 1) {
		for(int i = 1;i <= _tot; i++)
			if(mx[i] == 1) {
				f[i+1][0] = f[i][1] % mod * f[i+1][0] % mod + f[i][0] % mod * f[i+1][0] % mod + f[i+1][1] % mod * f[i][0] % mod;
				f[i+1][1] = f[i][1] % mod * f[i+1][1] % mod;	
				fl[i] = 1;
			}
		for(int i = 1;i <= tot; i++)
			if(!fl[i])
				f_f[++oo][0] = f[i][0] % mod,f_f[oo][1] = f[i][1] % mod;
		for(int i = 2;i <= oo; i++) {			
			f_f[i][1] = f_f[i][0] % mod * f_f[i-1][1] % mod + f_f[i][1] % mod * f_f[i-1][0] % mod + f_f[i][1] % mod * f_f[i-1][1] % mod;
			f_f[i][0] = f_f[i-1][0] % mod * f_f[i][0] % mod;
		}
	}
	kkk o;
	o._0 = f_f[oo][0] % mod;
	o._1 = f_f[oo][1] % mod;
	return o;
}

int main() {
	scanf("%d",&n);
	cin >> l1;
	for(int i = 0;i < n; i++) {
		if(l1[i] == '(') {
			l = l + l1[i];
			continue;
		}
		if(l1[i] == '+' || l1[i] == '*') {
			if(i == 0 || l1[i-1] != ')') {
				l = l + '_' + l1[i];
				continue;
			}
			l = l + l1[i];
		}
		if(l1[i] == ')' && l1[i-1] != ')') {
			l = l + '_' + l1[i];
			continue;
		}
		if(l1[i] == ')')
			l = l + ')';
	}
	sum = l.length();
	if(l[sum-1] != ')') l = l + '_';
	sum = l.length();
	maxin(1,0);
	bool lm = 0;
	for(int i = 2;i <= _num; i++) {
		if(fh[i] == 1 && !flag) {
			ans[i+1][0] = ans[i][1] % mod * ans[i+1][0] % mod + ans[i][0] % mod * ans[i+1][0] % mod + ans[i+1][1] % mod * ans[i][0] % mod;
			ans[i+1][1] = ans[i][1] % mod * ans[i+1][1] % mod;
			vis[i] = 1;
		}
		if(fh[i] == 1 && flag) {
			ans[i][0] = ans[i-1][1] % mod * ans[i][0] % mod + ans[i-1][0] % mod * ans[i][0] % mod + ans[i][1] % mod * ans[i-1][0] % mod;
			ans[i][1] = ans[i-1][1] % mod * ans[i][1] % mod;
			vis[i-1] = 1;
			lm = 1;
		}
	}
	sum = 0;
		for(int i = 2;i <= num; i++)
			if(!vis[i])
				f_ans[++sum][0] = ans[i][0] % mod,f_ans[sum][1] = ans[i][1] % mod;
	for(int i = 2;i <= sum; i++) {			
		f_ans[i][1] = f_ans[i][0] % mod * f_ans[i-1][1] % mod + f_ans[i][1] % mod * f_ans[i-1][0] % mod + f_ans[i][1] % mod * f_ans[i-1][1] % mod;
		f_ans[i][0] = f_ans[i-1][0] % mod * f_ans[i][0] % mod;
	}
	printf("%d ",f_ans[sum][0] % mod);
	return 0;
}