E:Infallibly Crack Perplexing Cryptarithm

题目来源:
CSUOJ 2295: Infallibly Crack Perplexing Cryptarithm
Codeforces Gym 101158E Infallibly Crack Perplexing Cryptarithm

语法分析

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define LD long double
#define ULL unsigned long long
#define UI unsigned int
#define _for(i,j,k) for(int i=j;i<=k;i++)
#define for_(i,j,k) for(int i=j;i>=k;i--)
#define lowbit(x) (x&-x)
#define ls(x) x<<1
#define rs(x) x<<1|1
//#pragma comment(linker, "/STACK:10240000000,10240000000")
using namespace std;
const int maxn = 1e5+5;
#define Result pair
#define Fail make_pair((char*)NULL,0)
char ctab[8]={'+','-','*','=','(',')','0','1'};
int vis[8],ta[10],cnt,an;
map<char,int> mse;
char s[35],sb[35];
Result Q(char* p); 
Result E(char* p);
Result T(char* p); 
Result F(char* p);
Result N(char* p); 
Result Q(char* p){ //计算等号:判断左右算式是否相等 
    Result left = E(p); //计算左边的算式
    if(left.first == NULL || *(left.first) != '=' ) return Fail;
    Result right = E(left.first + 1);
    if(right.first == NULL || right.second != left.second || *(right.first) != 0) return Fail;//
    return right; 
}
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;
    while(*(ret.first)=='*'){
        Result tmp = T(ret.first+1); //这里可以是递归调用自身 
        if(tmp.first == NULL) return Fail;
        ret.second *= tmp.second;
        ret.first = tmp.first;
    } 
    return ret;
}
Result F(char* p){ //计算负号和括号 
    Result ret = Fail;
    if(*p == '-'){
        ret = F(p+1);
        if(ret.first == NULL) return Fail;
        ret.second = -ret.second;
    }
    else if(*p == '('){
        ret = E(p+1); //括号内又是一个式子了 
        if(ret.first == NULL || *(ret.first)!=')') return Fail;
        ret.first ++;
    }
    else{
        ret = N(p);
    }
    return ret;
}
Result N(char* p){ //计算数字 
    if(!isdigit(*p)) return Fail; //应该是数字却不是 
    if(*p == '0' && isdigit(*(p+1))) return Fail; //有前置零 
    Result ret = make_pair(p,0); 
    while(isdigit(*ret.first)){
        (ret.second<<=1) += (*ret.first) - '0';
        ret.first++;
    }
    return ret;
}
void solve(){
    for(int i=0;s[i];i++){
        if(mse.count(s[i])){
            sb[i]=ctab[ta[mse[s[i]]]];
        }
        else sb[i]=s[i];
    }
    //cout<
    if(Q(sb).first != NULL ) an++;
}
void dfs(int d){
    if(d==cnt){
        solve();
        return;
    }
    _for(i,0,7){
        if(!vis[i]){
            vis[i]=1;
            ta[d]=i;
            dfs(d+1);
            vis[i]=0;
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>s;
    for(int i=0;s[i];i++) if(isalpha(s[i])&&(!mse.count(s[i])))  mse[s[i]]=cnt++;
    if(cnt>8){
        cout<<"0";
        return 0;
    }
    else if(cnt==0){
        if(Q(s).first != NULL) an++;
    }
    else{
        dfs(0);
    }
    cout<<an;
    return 0;
}

你可能感兴趣的:(补提,题解)