zoukankan      html  css  js  c++  java
  • 触手不及(巴科斯范式求表达式树)

    本题为学军神犇 cxt 出的神题。

    题意

    为了避免流露出自己的感情伤害别人, 小 M.M.T. 决定通过一个表达式来传递心意.

    给出一个等式.

    等式左边是一个 (int) 范围内的数, 等式右边是一个合法的 c++ 表达式.

    例如:(233 = 66 ∗ 4 − 31)

    保证等式右边只包含数字 (x (x ∈ [0, p),p) 是给定的质数()), 加号, 减号, 乘号, 除号, 左右括号.

    保证等式中没有任何空格,tab 等不可见字符. 而且保证合法。

    但是遗憾的是, 因为一些原因, 该等式不保证成立.

    于是, 小 M.M.T. 希望知道, 在模 (p) 意义下, 她的表达式的每个数字 (x) ,需要变成多少才能使等式成立.

    保证原不等式不存在除 (0), 你需要保证把数字变成 (x) 之后等式仍然不会除 (0).

    如果无论 (x) 取多少都不能使等式成立, 则输出 (No~Solution) .

    如果无论 (x) 取多少都能使等式成立, 则输出 (-1) .

    (len,p le 5 imes 10^6)

    题解

    首先很显然的根据给出的中缀表达式来求出二叉表达式树,如何求呢?

    其实可以直接递归模拟这个过程。

    这就是著名的 BNF(巴科斯范式) ,一种用递归的思想来表述计算机语言符号集的定义规范。

    以下函数的名称全部参考自 BNF

    1. 首先最外面一层是由很多 (+,-) 号构成的优先级最低的符号,我们最外层处理这个,称为 (expr) (表达式)。
    2. 然后会接下来会分成很多个子表达式,每个最终会代表成一个值,我们把处理这单独一串值称为 (term) (相)。
    3. 每个 $term $ 是可能由 (0) 个,甚至多个 (* ,/) 连接一些数成的表达式,我们接下来就需要求那些数叫 (factor) (因子)
    4. 然后 (factor) 就会分成两种情况,要么为单独一个数(求单个数的为 (digit) ),要么就是以括号开头,然后继续是一个完整的表达式 (expr)

    就这样不断递归处理,就可以处理出这颗二叉树了。

    说起来似乎很玄学,如果看过代码后,就应该会觉得很好理解了。

    整体思路就是,(expr) 实际上就是很多 (term)(+,-) 连接起来的表达式。同理 (term) 就是很多 (factor)(*) 号连接起来的乘积,(factor) 要么是个 (digit) 要么是个用 (()) 包起来的 (expr)

    然后处理出这颗表达式二叉树后,就很好做了,我们令 Dfs(o, val) 表示 (o) 这颗子树(表达式)需要满足等式成立需要的改变成 (val)

    递归下去处理,每次用四则运算的逆运算实现就行了。(此处需要预处理每个子树本来代表的值)

    注意,叶子就是最后的数字。

    然后有几个特殊情况。

    1. 当前区间运算为 (*) ,对于其中一颗子树来说,另一颗子树的值为 (0) ,有两种情况。
      • (val ot = 0) ,怎么改变都不能成立,那么那颗子树内所有点都为 (No~Solution)
      • (val = 0) ,怎么改变都可以成立,那么那颗子树内所有点都为 (-1)
    2. 当前区间运算为 (/) ,有两种特殊情况。
      • (val = 0) 并且左儿子值 ( ot = 0) ,那么右儿子整个无解。
      • (val ot = 0) 并且左儿子值 (= 0) ,那么右儿子也是无解。

    标程少判了最后一个情况,数据出锅了,差评。

    代码

    其实还是挺好 写的。

    #include <bits/stdc++.h>
    
    #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
    #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
    #define Set(a, v) memset(a, v, sizeof(a))
    #define Cpy(a, b) memcpy(a, b, sizeof(a))
    #define debug(x) cout << #x << ": " << (x) << endl
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    
    using namespace std;
    
    inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
    inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
    
    inline int read() {
        int x = 0, fh = 1; char ch = getchar();
        for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
        for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
        return x * fh;
    }
    
    void File() {
    #ifdef zjp_shadow
    	freopen ("expression.in", "r", stdin);
    	freopen ("expression.out", "w", stdout);
    #endif
    }
    
    const int N = 5e6 + 1e3, Maxn = N << 1;
    
    int Mod, Inv[N]; char str[N];
    
    #define ls(o) ch[o][0]
    #define rs(o) ch[o][1]
    
    inline int Add(int a, int b) { return (a += b) >= Mod ? a - Mod : a; }
    
    namespace Expression {
    
    	char *Head;
    
    	int Size, ch[Maxn][2], val[Maxn], opt[Maxn];
    
    	inline void Push_Up(int o) {
    		if (opt[o] == 0) val[o] = Add(val[ls(o)], val[rs(o)]);
    		if (opt[o] == 1) val[o] = Add(val[ls(o)], Mod - val[rs(o)]);
    		if (opt[o] == 2) val[o] = 1ll * val[ls(o)] * val[rs(o)] % Mod;
    		if (opt[o] == 3) val[o] = 1ll * val[ls(o)] * Inv[val[rs(o)]] % Mod;
    	}
    
    	inline int Digit();
    	inline int Factor();
    	inline int Term();
    	inline int Expr();
    
    	inline int Digit() {
    		int res = 0;
    		for (; isdigit(*Head); ++ Head) res = (res * 10) + (*Head ^ 48) ;
    		return res;
    	}
    
    	inline int Factor() {
    		int Node = 0;
    		if (*Head == '(')
    			++ Head, Node = Expr(), ++ Head;
    		else 
    			val[Node = ++ Size] = Digit();
    		return Node;
    	}
    
    	inline int Term() {
    		int Last = Factor(), Node = Last;
    		while (*Head == '*' || *Head == '/') {
    			opt[Node = ++ Size] = 2 + (*Head ++ == '/');
    			ls(Node) = Last; rs(Node) = Factor();
    			Push_Up(Last = Node);
    		}
    		return Node;
    	}
    
    	inline int Expr() {
    		int Last = Term(), Node = Last;
    		while (*Head == '+' || *Head == '-') {
    			opt[Node = ++ Size] = (*Head ++ == '-');
    			ls(Node) = Last; rs(Node) = Term();
    			Push_Up(Last = Node);
    		}
    		return Node;
    	}
    
    	void Print(int o, const char* ans) {
    		if (!ls(o) && !rs(o)) 
    			return (void) puts(ans);
    		Print(ls(o), ans); Print(rs(o), ans);
    	}
    
    	void Dfs(int o, int Val) {
    		if (!ls(o) && !rs(o))
    			return (void) printf ("%d
    ", Val);
    		if (opt[o] == 0) {
    			Dfs(ls(o), Add(Val, Mod - val[rs(o)]));
    			Dfs(rs(o), Add(Val, Mod - val[ls(o)]));
    		}
    		if (opt[o] == 1) {
    			Dfs(ls(o), Add(Val, val[rs(o)]));
    			Dfs(rs(o), Add(val[ls(o)], Mod - Val));
    		}
    		if (opt[o] == 2) {
    			For (dir, 0, 1)
    				if (val[ch[o][dir ^ 1]])
    					Dfs(ch[o][dir], 1ll * Val * Inv[val[ch[o][dir ^ 1]]] % Mod);
    				else
    					Print(ch[o][dir], Val ? "No Solution" : "-1");
    		}
    		if (opt[o] == 3) {
    			Dfs(ls(o), 1ll * Val * val[rs(o)] % Mod);
    			if (Val && val[ls[o]]) 
    				Dfs(rs(o), 1ll * val[ls(o)] * Inv[Val] % Mod);
    			else 
    				Print(rs(o), "No Solution");
    		}
    	}
    
    	char Sign[4] = {'+', '-', '*', '/'};
    	void Out(int o) {
    		if (!o) return ;
    		if (!ls(o) && !rs(o))
    			return (void) printf (" %d ", val[o]);
    		Out(ls(o));
    		putchar (Sign[opt[o]]);
    		Out(rs(o));
    	}
    
    };
    
    void Solve() {
    	using namespace Expression;
    	Head = str;
    	int Base = Digit() % Mod; ++ Head;
    	int root = Expr();
    	Dfs(root, Base);
    }
    
    int main () {
    
    	File();
    
    	read(); Mod = read(); scanf ("%s", str);
    
    	Inv[0] = Inv[1] = 1;
    	For (i, 2, Mod - 1) Inv[i] = 1ll * Inv[Mod % i] * (Mod - Mod / i) % Mod;
    	Solve();
    
    	return 0;
    }
    
  • 相关阅读:
    dedecms内容管理系统使用心得
    flex>样式和主题 小强斋
    flex>样式和主题 小强斋
    flex>HttpService 小强斋
    Flex>连接WebService 小强斋
    flex>HttpService 小强斋
    Struts2>Cannot find the tag library descriptor for /strutstags 小强斋
    flex>HttpService 小强斋
    Flex>连接WebService 小强斋
    Flex>连接WebService 小强斋
  • 原文地址:https://www.cnblogs.com/zjp-shadow/p/9676609.html
Copyright © 2011-2022 走看看