洛谷 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章