zoukankan      html  css  js  c++  java
  • [codechef] REBIT:准备好每一位(表达式/DP)

    Problem

    题目地址

    Solution

    前置知识

    中缀表示式序列可以转化成一棵二叉树。发现计算概率可以转化成计数,在二叉树上做一个树形DP就好了。

    Code

    Talk is cheap.Show me the code.

    #include<bits/stdc++.h>
    using namespace std;
    typedef int LL;
    #define int long long
    inline int read() {
        int x = 0, f = 1; char ch = getchar();
        while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
        return x * f;
    }
    const int N = 1e6+7, mod = 998244353;
    int len,tot;
    int ls[N],rs[N];
    int f[N][4];
    char str[N],c[N];
    struct Node {
    	int x,y;
    	Node operator & (const Node &el) const {
    		return (Node)<%x&el.x, y&el.y%>;
    	}
    	Node operator | (const Node &el) const {
    		return (Node)<%x|el.x, y|el.y%>;
    	}
    	Node operator ^ (const Node &el) const {
    		return (Node)<%x^el.x, y^el.y%>;
    	}
    	bool operator < (const Node &el) const {
    		return (x==el.x ? y<el.y : x<el.x);
    	}
    };
    map<int,Node> inode;
    map<Node,int> acinode;
    void Init() {
    	inode[0] = (Node)<%0,0%>, inode[1] = (Node)<%1,1%>, inode[2] = (Node)<%0,1%>, inode[3] = (Node)<%1,0%>;
    	acinode[(Node)<%0,0%>] = 0, acinode[(Node)<%1,1%>] = 1, acinode[(Node)<%0,1%>] = 2, acinode[(Node)<%1,0%>] = 3;
    }
    inline void Add(int &x,int y) {
    	x = (x+y>mod ? x+y-mod : x+y);
    }
    void Dfs(int u) {
    	int x = ls[u], y = rs[u];
    	if(x) {
    		Dfs(x); Dfs(y);
    	} else return ;
    	for(int i=0;i<4;++i) {
    		Node ii = inode[i];
    		for(int j=0;j<4;++j) {
    			Node jj = inode[j];
    			if(c[u] == '&') {
    				Add(f[u][acinode[ii & jj]], f[x][i]*f[y][j]%mod);
    			} else if(c[u] == '|') {
    				Add(f[u][acinode[ii | jj]], f[x][i]*f[y][j]%mod);
    			} else if(c[u] == '^') {
    				Add(f[u][acinode[ii ^ jj]], f[x][i]*f[y][j]%mod);
    			}
    		}
    	}
    }
    int Pow(int x,int y) {
    	int res = 1, base = x;
    	while(y) {
    		if(y&1) res = res*base%mod; base = base*base%mod; y >>= 1;
    	}
    	return res;
    }
    void work() {
    	for(int i=1;i<=tot;++i) {
    		c[i] = ls[i] = rs[i] = 0;
    		for(int j=0;j<4;++j) f[i][j] = 0;
    	}
    	tot = 0;
    	scanf("%s",str+1); len = strlen(str+1)
    	stack<char> sta; stack<int> num;
    	for(int i=0;i<=len+1;++i) {
    		if(str[i] == '(') {
    			sta.push(str[i]);
    		} else if(str[i] == ')') {
    			while(sta.top() != '(') {
    				char opt = sta.top(); sta.pop();
    				int x = num.top(); num.pop();
    				int y = num.top(); num.pop();
    				c[++tot] = opt; ls[tot] = y, rs[tot] = x;
    				num.push(tot);
    			}
    			sta.pop();
    		} else if(str[i] == '#') {
    			c[++tot] = str[i]; num.push(tot);
    		} else {
    			sta.push(str[i]);
    		}
    	}
    	for(int i=1;i<=tot;++i) {
    		if(!ls[i]) {
    			for(int j=0;j<4;++j) f[i][j] = 1;
    		}
    	}
    	Dfs(tot);
    	int sum = 0;
    	for(int i=0;i<4;++i) Add(sum, f[tot][i]);
    	int inv = Pow(sum,mod-2);
    	for(int i=0;i<4;++i) printf("%lld ",f[tot][i]*inv%mod);
    	puts("");
    }
    signed main()
    {
    	Init();
    	int T = read();
    	while(T--) work();
    	return 0;
    }
    /*
    2
    #
    (#&#)
    ()
    
    748683265 748683265 748683265 748683265
    436731905 935854081 811073537 811073537
    */
    

    Summary

    • 中缀表示式序列可以转化成一棵二叉树。从而将此类问题转化为树上问题。
  • 相关阅读:
    高阶函数
    js严格模式
    改变函数内this指向方法——call、apply、bind
    vue动态组件
    微信支付接口IP获取与调用之统一下单
    node.js实现微信公众号支付
    微信支付(公众号支付JSAPI)--转载
    公众号微信支付流程-(转)
    python 3 代码一模一样,出现运行结果不同的情况(只是不以为一样而已)
    pycharm设置自动换行
  • 原文地址:https://www.cnblogs.com/BaseAI/p/13992483.html
Copyright © 2011-2022 走看看