• 牛客练习赛47 A DongDong破密码 (异或性质,递推)


    链接:https://ac.nowcoder.com/acm/contest/904/A
    来源:牛客网

    DongDong破密码
    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 131072K,其他语言262144K
    64bit IO Format: %lld
    题目描述
    DongDong是一个喜欢密码学的女孩子,她养的萨摩耶叼着一张带着加密信息的纸条交给了她,如果她不能破解这张密码,萨摩耶是不会高兴的。

    给定n,m,给出长度为n的01串,每次向后移动一位,移动m-1次,最后求出这n+m-1位每一位的异或值(00=0,11=0,0^1=1)成为密码。(如下图这样,此时n=6,m=3)

    输入描述:
    第一行两个整数,n和m

    第二行一个01串(共n+m-1位)

    2<=n+m<=1000000
    输出描述:
    第一行输出答案:长度为n的01串(保证存在答案)
    示例1
    输入
    复制
    6 3
    11010110
    输出
    复制
    101010
    说明
    见题目描述

    题意:

    思路:

    这种题肯定是要用到异或的性质的。

    可以看我这一篇博客:https://www.cnblogs.com/qieqiemin/p/11290854.html

    接下来我们来看这题

    由图我们可以看到,原始字符串ans的第一个字符一定和结果字符串str的第一个字符相等,那么我们可以直接得来值。

    再看图中我蓝色圈的两个,每一个ans字符与m-1个他之前的字符异或得到结果字符,图中右边的蓝色框向下度,好左边的蓝色框向左读是一样的。那么我们就可以维护一下 一个数值now 表示当前字符的前面 m-1个字符(不足m-1个的话,用0补充,即异或0也是数值不变。)的异或结果。

    为什么可以维护? 因为我们是要从ans的第一个字符开始找,从左到右的过程是很容易维护前面状态的。

    细节见代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
    inline void getInt(int* p);
    const int maxn = 1000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int n,m;
    string str;
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        gbtb;
        cin>>n>>m;
        cin>>str;
        string ans="";
        int now;
        if(str[0]=='0')
        {
            ans.pb('0');
            now=0;
        }else
        {
            ans.pb('1');
            now=1;
        }
        for(int i=1;i<min(n,m);++i)
        {
            if(str[i]=='1')
            {
                if(now==0)
                {
                    ans.pb('1');
                }else
                {
                    ans.pb('0');
                    // now=0;
                }
                now=1;
            }else
            {
                if(now==0)
                {
                    ans.pb('0');
                }else
                {
                    ans.pb('1');
                    // now=1;
                }
                    now=0;
            }
        }
        now=0;
        for(int i=1;i<min(n,m);i++)
        {
            now^=(ans[i]-'0');
        }
        for(int i=m;i<n;++i)
        {
            if(str[i]=='1')
            {
                if(now==1)
                {
                    ans.pb('0');
                }else
                {
                    ans.pb('1');
                }
            }else
            {
                if(now==1)
                {
                    ans.pb('1');
                }else
                {
                    ans.pb('0');
                }
            }
            now^=(ans[i-m+1]-'0');
            now^=(ans[i]-'0');
        }
        cout<<ans<<endl;
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    [再寄小读者之数学篇](2014-06-19 满足三个积分等式的函数)
    [再寄小读者之数学篇](2014-06-19 微分等式的结论)
    我的一些武功
    TEX学习笔记
    我的一些诗词
    我的课程与学生
    [再寄小读者之数学篇](2014-06-19 三维插值公式)
    [再寄小读者之数学篇](2014-06-19 旋度公式)
    JAVA小项目实例源码—学习娱乐小助手
    可拖拽的3D盒子
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11290881.html
Copyright © 2020-2023  润新知