P1013 [NOIP1998 提高组] 进制位

题目的意思非常的简单,就是某进制下通过一些数字的加法运算,来推演这些数字。

但是,某蒟蒻想了足足一晚上,才理解了下面两个解题的关键……(这是对这篇题解的一点点补充)

第一点:该表进制为 𝑁−1N−1

首先假设该表中有二位数(不可能存在三位或以上的数),那么这个二位数(假设是 𝐴𝐶AC),那么显然的有 𝐴=1A=1。

那如果没有两位数,怎么办?

稍稍思考一下,不可能存在没有两位数的情况。因为考虑 𝑁≥3N≥3,所有至少两个数。两个数最小为 00 和 11,那么显然,会产生 1+1=21+1=2。而 22 要么是该进制下的一个两位数,要么就是一个新的数;显然,若 22 是一个新的数,那么又会产生 1+2=31+2=3 和 2+2=42+2=4……如此下去,表中的 𝑁−1N−1 个数必然是 𝑁−1N−1 进制下的 0∼𝑁−20∼N−2 ,也就必然会产生两位数。

第二点:每行有几个两位数,那么这个数就是几

假设已知当前的表为 𝑘k 进制,考虑一个数它为 𝑥x,那么 𝑥+𝑘−𝑥∼𝑥+𝑘−1x+k−x∼x+k−1 必然都是两位数,一共 𝑥+𝑘−1−(𝑥+𝑘−𝑥)+1=𝑥+𝑘−1−𝑥−𝑘+𝑥+1=𝑥x+k−1−(x+k−x)+1=x+k−1−x−k+x+1=x 个。所以,一行有几个两位数,这个数就是几。

理解这两点,我们就可以非常轻松地打代码啦。

记得加上无解的判定,一定要考虑全面。

#include <bits/stdc++.h>
using namespace std;

string s,d[10][10];
int N;
char ans[10];
int ans2[10];
map<char,int> t;
void check(int x,int y) {
    if(x!=y&&ans2[x]==ans2[y]) {
        cout<<"ERROR!"<<endl;
        exit(0);
    }
    if(d[x][y].size()==2&&t[d[x][y][0]]!=1) {
        cout<<"ERROR!"<<endl;
        exit(0);
    }
    if(d[x][y].size()==1) {
        if(ans2[x]+ans2[y]>=N-1) {
            cout<<"ERROR!"<<endl;
            exit(0);
        }
        int a=ans2[x]+ans2[y];
        if(a!=t[d[x][y][0]]) {
            cout<<"ERROR!"<<endl;
            exit(0);
        }
    }
    if(d[x][y].size()==2) {
        if(ans2[x]+ans2[y]<N-1) {
            cout<<"ERROR!"<<endl;
            exit(0);
        }
        int a=ans2[x]+ans2[y];
        if(a%(N-1)!=t[d[x][y][1]]) {
            cout<<"ERROR!"<<endl;
            exit(0);
        }
        if(t[d[x][y][0]]!=1) {
            cout<<"ERROR!"<<endl;
            exit(0);
        }
    }
    return ;
}

int main() {
    cin>>N;
    for(int i=0;i<N;i++) {
        for(int j=0;j<N;j++) {
            cin>>s,d[i][j]=s;
            if(i==0) continue;
            if(j==0) ans[i]=s[0];
            else if(s.size()==2) ans2[i]++;
        }
        if(i!=0) t[ans[i]]=ans2[i];
    }
    for(int i=1;i<N;i++) for(int j=1;j<N;j++) check(i,j);
    for(int i=1;i<N;i++) cout<<ans[i]<<"="<<ans2[i]<<" ";
    cout<<endl<<N-1<<endl;
    return 0;
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值