Equation

Equation ( equation )
【题目描述】
给定一个等式,其格式为 p ◦ q = r,其中 1 ≤ p,q,r < 10 9 ,算符 ◦ 可以是 +、- 或
*(表示乘法)。
p,q 和 r 中的某些数字被替换成了大写字母,例如 A09 + C0B = 6AC。你的任务
是找出所有大写字母代表的数字,使得等式成立。
你需要遵循下列规则:
1. 相同的字母替换成相同的数字,不同的字母替换成不同的数字。
2. p、q 和 r 不能以 0 开头。
称两个方案不同,如果存在一个字母被替换成了不同的数字。考虑到方案数可能很
多,你只需要输出合法方案的数量。注意如果没有方法使得等式成立,你应该输出 0。
【输入格式】
从文件 equation.in 中读入数据。
输入只有一行,表示需要处理的等式。
保证最多只有 9 个不同的字母,等式中不会出现空格。
【输出格式】
输出到文件 equation.out 中。
输出一个整数,表示方案的数量。
【样例 1 输入】
A09+C0B=6AC
【样例 1 输出】
1
【样例 1 解释】
唯一合法的方案是 109 + 506 = 615。
【样例 2 输入】
P*Q=P
第 5 页 共 8 页
NOIP 模拟题 Equation(equation)
【样例 2 输出】
8
【样例 3 输入】
CANADA-MAR8=CCC
【样例 3 输出】
0
【子任务】
总共有 10 个测试点。
对于测试点 1 ∼ 3,等式中最多有 3 个不同的字母。
对于测试点 1、2、4、7 和 8,◦ 只可能是 + 或 -。
对于测试点 1、4、5 和 6,每个字母只会出现一次。


找遍了我知道的所有的OJ,发现并没有这道题

很苦逼的找了AC代码对拍,然后发现我考场上发一个字符打了两遍,只有70pts,心态崩了

好像还T了一个点,pow函数是真的慢

题不是很难,爆搜,枚举每个字母的数字,其实就是一个全排列,卡卡常就行

网上没什么好的数据,我就随便给一发:

输入:

ABCDEFGH-BCDEFGH=AIIIIIII

输出:

362880

下面给出代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
inline long long rd(){
    long long x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
inline void write(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}
char a[10006];
bool book[10006];
long long h[100006];
char vis[10006];
int cnt;
int len=0,fir,sec,f=0;
long long ans=0;
bool map[100006];
long long s[10006];
long long p[10006];
inline long long check(){
    long long A=0,b=0,c=0;
    int set=fir;
    while(set--){
        if(set==0) break;
        if(isdigit(a[set])) A+=((a[set]-'0')*p[fir-set-1]);
        else A=A+(s[a[set]-'0']*p[fir-set-1]);
    }
    set=sec;
    while(set--){
        if(a[set]=='+'||a[set]=='-'||a[set]=='*') break;
        if(isdigit(a[set])) b+=((a[set]-'0')*p[sec-set-1]);
        else b=b+(s[a[set]-'0']*p[sec-set-1]);
    }    
    for(register int j=len;j>sec;j--){
        if(isdigit(a[j])) c+=((a[j]-'0')*p[len-j]);
        else c=c+(s[a[j]-'0']*p[len-j]);
    }
    if(f==1&&A-b==c) return 1;
    if(f==2&&A+b==c) return 1;
    if(f==3&&A*b==c) return 1;
    return 0;
}
inline void dfs(int x){
    if(x==cnt+1){
        if(check()) ans++;
        return ;
    }
    for(register int i=0;i<=9;i++){
        if(i==0&&h[vis[x]-'0']) continue;
        if(map[i]) continue;
        map[i]=1;
        s[vis[x]-'0']=i;
        dfs(x+1);
        s[vis[x]-'0']=-1;
        map[i]=0;
    }
    return ;
}
int main(){
    //freopen("equation.in","r",stdin);
    //freopen("equation.out","w",stdout);
    p[0]=1;
    for(int i=1;i<=10;i++) p[i]=p[i-1]*10;
    memset(s,-1,sizeof(s));
    scanf("%s",a+1);
    len=strlen(a+1);
    for(register int i=1;i<=len;i++){
        if(a[i]=='-') f=1;
        if(a[i]=='+') f=2;
        if(a[i]=='*') f=3;
        if(a[i]=='-'||a[i]=='+'||a[i]=='*') fir=i;
        if(a[i]=='=') sec=i;
        if(book[a[i]-'0']==0){
            book[a[i]-'0']=1;
            if(a[i]!='+'&&a[i]!='*'&&a[i]!='-'&&a[i]!='='&&!isdigit(a[i])) vis[++cnt]=a[i];
        }
        if(i==1||a[i-1]=='='||a[i-1]=='+'||a[i-1]=='-'||a[i-1]=='*') h[a[i]-'0']=1;
    }
    dfs(1);
    write(ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WWHHTT/p/9746895.html
今日推荐