星星之火OIer:虫食算

题目链接

退役题解

同时致敬我的第一篇题解

这是一道搜索题

依次枚举每一个字母的值

然后要从低位开始搜

提前算进位

更多解释看代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
bool flag[95];
char a[28],b[28],c[28],d[28];
int v[95],n,tot;
inline void ycl() {//预处理,从低位到高位统计,以免重复计算进位
    for(int i=n-1;i>=0;i--) {
        if(!flag[a[i]]) {//每一个字母只统计一次
            flag[a[i]]=1;
            d[++tot]=a[i];//最先的肯定是最低位
        }
        if(!flag[b[i]]) {
            flag[b[i]]=1;
            d[++tot]=b[i];
        }
        if(!flag[c[i]]) {
            flag[c[i]]=1;
            d[++tot]=c[i];
        }
    }
    memset(flag,0,sizeof(flag));
    memset(v,-1,sizeof(v));//一定有一个字母为0,清为-1
}
inline bool check() {
    for(int i=n-1;i>=0;i--) {//从低位到高位每一位都要check
        if(v[a[i]]!=-1&&v[b[i]]!=-1&&v[c[i]]!=-1) {//三个数字都知道
            if((v[a[i]]+v[b[i]])%n!=v[c[i]]&&(v[a[i]]+v[b[i]]+1)%n!=v[c[i]])//a[i]+b[i]正好是c[i]或进了一位
                return 0;
        }
        else if(v[a[i]]!=-1&&v[b[i]]!=-1&&v[c[i]]==-1) {//下面三个都是确定两个之后剩下的一个就只有两种可能(正好或进(退)位)
            if(flag[(v[a[i]]+v[b[i]])%n]&&flag[(v[a[i]]+v[b[i]]+1)%n])//如果这个两个可能的数都被用过,肯定不是正解
                return 0;
        }
        else if(v[a[i]]!=-1&&v[b[i]]==-1&&v[c[i]]!=-1) {
            if(flag[(v[c[i]]-v[a[i]]+n)%n]&&flag[(v[c[i]]-v[a[i]]-1+n)%n])
                return 0;
        }
        else if(v[a[i]]==-1&&v[b[i]]!=-1&&v[c[i]]!=-1) {
            if(flag[(v[c[i]]-v[b[i]]+n)%n]&&flag[(v[c[i]]-v[b[i]]-1+n)%n])
                return 0;
        }
    }
    return 1;
}
inline bool ok() {//从低位到高位依次比对
    int jw=0;//进位
    for(int i=n-1;i>=0;i--) {
        if((v[a[i]]+v[b[i]]+jw)%n!=v[c[i]])//结果不等
            return 0;//肯定不对
        jw=(v[a[i]]+v[b[i]]+jw)/n;//计算有没有进位
    }
    if(jw)//如果计算完了仍然有进位,肯定是错的
        return 0;
    return 1;
}
inline void pr() {
    for(int i='A';i<='A'-1+n;i++)//v[i]就是i这个字母所代表的值
        if(v[i]!=-1)
            printf("%d ",v[i]);
    exit(0);//直接结束全部程序
}
void dfs(int x) {
    if(x>n) {//所有位数都已确定
        if(ok()) {//计算正确
            pr();//输出答案
        }
        return;//不管怎样都要返回
    }
    for(int i=n-1;i>=0;i--) {
        if(flag[i])//i这个值被用过
            continue;
        v[d[x]]=i;//将字母d[x]的值设定为i
        flag[i]=1;//i已被用过
        if(!check()) {//已经不成立
            v[d[x]]=-1;
            flag[i]=0;
            continue;//回溯
        }
        dfs(x+1);//继续搜
        v[d[x]]=-1;//回溯
        flag[i]=0;
    }
}
int main() {
    scanf("%d%s%s%s",&n,a,b,c);
    ycl();
    dfs(1);
}

 

Visual Studio Code (VSCode) 是一个非常流行的开源代码编辑器,因其高度可扩展性和丰富的插件生态系统而受到开发者喜爱。对于面向算法和竞赛编程 (OI/ACM) 的开发者来说,有一些插件可以帮助提升编写、测试和优化代码的效率。以下是几个推荐的 VSCode 插件,它们可以为 OIer 提供支持: 1. **C/C++**: - C/C++ Extension Pack:包含了基本的C/C++语言支持,以及调试工具。 - Clangd Language Server:提供自动完成、错误检测等功能,适用于竞赛中的高效编程。 2. **代码高亮和语法提示**: - C/C++ Intellisense:增强的语法高亮和代码提示。 - C++ LSP (Language Server Protocol) Extensions:例如, "C++ Enhanced" 提供更全面的代码提示。 3. **代码片段和模板**: - Live Share C++:支持多人协作,可以分享代码片段和模板。 - C/C++ Snippets:自定义代码片段,快速输入常见代码模式。 4. **调试**: - Debugger for GDB/LLDB:如果你使用GDB或LLDB作为调试器,这个插件必不可少。 5. **代码格式化**: - C/C++ Prettier Code Formatter:自动格式化代码风格,保持一致性。 6. **竞赛管理**: - Competitive Programming Tools:提供题目管理、提交、测试等功能,帮助组织和跟踪竞赛进度。 7. **版本控制**: - GitLens:强大的Git功能,方便版本管理和代码比较。 8. **Markdown**: - Markdown All in One:编写文档时常用的工具,因为算法题解经常用到Markdown。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值