寒假每日一题(1.2)解析

通过题目分析,我们可以知道该题是通过键盘分别输出一个二进制和一个三进制数,然后在0~10^{9}的范围内找到一个数N,使得N分别在二进制和三进制表示下与从键盘输入的两个数据分别只有一位不同。

那么很容易想到的思路便是暴力枚举0~10^{9}范围内的所有数,枚举完之后再将数转化为二进制和三进制分别判断即可,但该种做法时间复杂度为10^{9}*log10^{9},显然超出了题目所要求的时间。因此,我们可以反向进行枚举从而降低时间复杂度,即先枚举和从键盘所输入的二进制数只有一位不同的数,那么与键盘所输入数据不同的情况只有4中情况即该数的第一、二、三、四位分别与所输入的数据的一、二、三、四位不同,同理我们枚举出和从键盘所输入的三进制只有一位不同的数,那么需要注意在三进制下,我们可以举个例子比如该位当前位为2,那么与他不同的情况分别为0和1,所以需要在这里每一位枚举两次。那么我们分别把在二进制和三进制下找出的两堆不同的数放入两个集合,我们在判断这个集合中的数是否在另一个集合中,此时可以用哈希表进行存储,又由于题中说明该题有唯一解,即我们找出两个集合的交集即为我们所需要找的数N

如果不会使用哈希表可以分别使用两个数组加上一个二层循环即可。

下面给出代码参考:

哈希表c++代码:

//本篇中的auto是让编译器自动去识别数据的类型,在本篇中也可以改为char
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>   //在c++中使用哈希表需要用该头文件
using namespace std;

int get(string s, int b)  // 将b进制的数转化成十进制
{
    int res = 0;
    // 秦九韶算法
    for (auto c: s)
        res = res * b + c - '0'; //在这里用秦九韶算法将b进制的数转化为十进制
    return res;
}

int main()
{
    string a, b;
    cin >> a >> b;               //从键盘分别读入二进制和三进制

    unordered_set<int> S;         //定义一个哈希表

    for (auto& c: a)     //用引用是因为在c变的情况之下a同时也要改变所以要在这里加上引用
    {
        c ^= 1;
        S.insert(get(a, 2));  //该for循环枚举和所输入二进制每一位不一样的所有数,即该位要么是1变为0要么从0变为1,那么此时异或1即可,然后再把调用进制转换 函数把其变为10进制存入哈希表s中
        c ^= 1;               //修改完之后再次异或1将其恢复为原状
    }

    for (auto& c: b)
    {
        char t = c;        //先将该位进行存储
        for (int i = 0; i < 3; i ++ )   //因为是三进制所以会有三种情况,在这里分别进行判断
            if (i + '0' != t)       //i+0是将这里的数字变换为ASCII码,如果与初始位不相等 
            {
                c = i + '0';        //那么就将其变为i
                int x = get(b, 3);  //三进制b转换为十进制结果
                if (S.count(x))    //判断x是否在s集合中出现过
                {
                    cout << x << endl; 
                    return 0;
                }
            }
        c = t;       //若没有找到,就要将c恢复为原状
    }

    return 0;
}

数组c++代码:

#include<bits/stdc++.h>
using namespace std;
set<int> s;
string o,t;
int main(){
    cin>>o>>t;
    int n=0,n1=0;
    int q=pow(2,o.length()-1),q1=pow(3,t.length()-1);
    //计算二进制对应数字n(十进制)
    for(int i=0;i<o.length();i++)
    {
        n=n*2+(o[i]-'0');
    }
    //计算三进制对应数字n1(十进制)
    for(int i=0;i<t.length();i++)
    {
        n1=n1*3+(t[i]-'0');
    }
    //计算二进制数改变每一位所能产生的所有可能情况,存入set内
    for(int i=0;i<o.length();i++)
    {
        if(!i&&o[i]=='0') s.insert(n+q);
        else if(o[i]=='1')s.insert(n-q);
        else if(o[i]=='0')s.insert(n+q);
        q/=2;
    }
    //计算三进制数改变每一位所能产生的所有可能情况,并且每计算一个,查看set内有没有,如果存在即为正确答案
    for(int i=0;i<t.length();i++){
        if(!i&&t[i]=='0'){
            if(s.count(n1+q1*1)){cout<<n1+q1*1;return 0;}
            if(s.count(n1+q1*2)){cout<<n1+q1*2;return 0;}
        }else{

            for(int j=0;j<3;j++){
                if(s.count(n1+ q1*( j-(t[i]-'0') ) )){
                    cout<<n1+ q1*( j-(t[i]-'0') );
                    return 0;
                }    
            }
        }
        q1/=3;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值