Codeforces Gym 101158 E. Infallibly Crack Perplexing Cryptarithm (模拟 + 语法分析)
2017-07-09 15:02
971 查看
AC代码
C++版本
/* 根据 定义的等式 的规则 判断给定串可以写成多少种二进制等式且成立的形式 解法: 通过语法分析的形式将多个表达式定义进行 递归下降的解析。 此方法可以不用过多考虑多种表达式定义组合的合法和非法情况,只需要完整解析单个表达式,并递归调用。 */ #include<bits/stdc++.h> using namespace std; #define Result pair<char*,int> #define FAIL make_pair((char*)NULL,0) char srcExpr[32], expr[32], op[8] = {'0', '1', '+', '-', '*', '(', ')', '='}; struct Parser { Result Q(char* p) { Result res = E(p); if(res.first == NULL || *(res.first) != '=') return FAIL; Result rgt = E(res.first+1); if(rgt.first == NULL || *(rgt.first) != 0 || rgt.second != res.second) return FAIL; return rgt; } Result E(char *p) { Result ret = T(p); if(ret.first == NULL) return FAIL; while(*(ret.first) == '+' || *(ret.first) == '-') { Result tmp = T(ret.first + 1); if(tmp.first == NULL) return FAIL; if(*(ret.first) == '-') ret.second -= tmp.second; else ret.second += tmp.second; ret.first = tmp.first; } return ret; } Result T(char *p) { Result ret = F(p); if(ret.first == NULL) return FAIL; if(*(ret.first) == '*') { Result tmp = T(ret.first + 1); if(tmp.first == NULL) return FAIL; ret.first = tmp.first, ret.second *= tmp.second; } return ret; } Result F(char *p) { Result ret; if(*p == '-') { Result ret = F(p+1); ret.second = -ret.second; return ret; } else if(*p == '(') { Result ret = E(p+1); if(ret.first == NULL || *(ret.first) != ')') return FAIL; ret.first++; return ret; } else { return N(p); } } Result N(char *p) { Result ret; if(!isdigit(*p)) return FAIL; if(*p == '0' && isdigit(*(p+1))) return FAIL; while(isdigit(*p)) { (ret.second *= 2) += (*p-'0'); p++; } ret.first = p; return ret; } }; int main() { sort(op, op+8); scanf("%s", srcExpr); map<char, int> mp; int idx = 0; for(int i=0;srcExpr[i];i++) { if(isalpha(srcExpr[i]) && mp.find( srcExpr[i] ) == mp.end()) mp[ srcExpr[i] ] = ++idx; } if(idx > 8) { printf("0\n"); return 0; } int ans = 0; do { for(int i=0;srcExpr[i];i++) expr[i] = (isalpha(srcExpr[i]) ? op[ mp[srcExpr[i]]-1 ] : srcExpr[i]); if(Parser().Q(expr).first != NULL) ans++; } while(next_permutation(op, op+8)); int factorial = 1; for(int i=1;i<=(8-idx);i++) factorial *= i; printf("%d\n", ans / factorial); }
Python版本
# 解法: # 总的有效符号为 8 种 + - * ( ) 0 1 = # 全排列枚举将有效符合去替换字母,通过 Python 的 eval 函数去判断等式左边 = 右边? (...我选择用 Python 过此题的唯一原因) # 同时题面中还有部分限制规则需要判断。 # Python eval 计算二进制数需形如 eval('0b101+0b10') 。 lst = ['0', '1', '+', '-', '*', '(', ')', '='] flg = [0 for i in range(8)] ans = [0 for i in range(8)] pos = [0 for i in range(256)] chr = [0 for i in range(200)] ok = list() s = str() cnt = 0 tot = [0] def jug(t): for i in range(len(t)): if t[i] in '+*': if i == 0 or t[i-1] in '(+*-': return True elif t[i] == '0': if (i > 0 and t[i-1] not in '01') and (i+1 < len(t) and t[i+1] in '01'): return True elif t[i] == '(': if i+1 < len(t) and t[i+1] == ')': return True return False def jugQ(): tmp = s[:] t = s[:] for i in range(1, cnt+1): t = t.replace(chr[i], ans[i-1]) while True: flag = False for i in range(1, len(t)): if (t[i-1] in '(+-*=') and (t[i] in '01'): t = t[:i] + 'b' + t[i:] flag = True break if flag == False: break if t[0] in '01': t = 'b' + t[:] t = t.replace('b', '0b') try: t1, t2 = t.split('=') if jug(t1) or jug(t2): return a1 = eval(t1) a2 = eval(t2) if a1 == a2 and t not in ok: ok.append(t) # print(tmp) # print(t) tot[0] += 1 except: return def dfs(idx): if idx == 8: # print(ans) jugQ() for i in range(8): if flg[i]: continue else: ans[idx] = lst[i] flg[i] = 1 dfs(idx+1) flg[i] = 0 if __name__ == "__main__": s = input() for c in s: if (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z'): if pos[ord(c)] > 0: continue else: cnt+=1 pos[ord(c)] = cnt chr[cnt] = c if cnt > 8: print(0) else: dfs(0) print(tot[0])
相关文章推荐
- Codeforces Gym 101158 B. Quality of Check Digits (模拟)
- 【模拟】BAPC2014 G Growling Gears (Codeforces GYM 100526)
- CodeForces Gym 100803A 模拟,贪心
- Codeforces Gym 100340C ePig 模拟
- Codeforces Gym 101158 F. Three Kingdoms of Bourdelot
- 【模拟】BAPC2014 G Growling Gears (Codeforces GYM 100526)
- 【模拟】NEERC15 J Jump (Codeforces GYM 100851)
- Codeforces Gym 101505(2016-2017 CTU Open Contest) D---群论、模拟
- 【模拟】ECNA 2015 I What's on the Grille? (Codeforces GYM 100825)
- codeforces gym 100357 K (表达式 模拟)
- 【模拟】NEERC15 J Jump(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
- 【模拟】ECNA 2015 I What's on the Grille? (Codeforces GYM 100825)
- codeforces Gym - 101190H——Hard Refactoring (模拟)
- codeforces Gym - 101190J ——Jenga Boom(模拟)
- 【模拟】NEERC15 A Adjustment Office (Codeforces GYM 100851)
- codeforces gym 100286 I iSharp (字符串模拟)
- 【模拟】NEERC15 A Adjustment Office (2015-2016 ACM-ICPC)(Codeforces GYM 100851)
- 【模拟】NEERC15 E Easy Problemset (Codeforces GYM 100851)
- 【模拟】NEERC15 G Generators (Codeforces GYM 100851)
- 【模拟】NEERC15 G Generators(2015-2016 ACM-ICPC)(Codeforces GYM 100851)