• CodeForces#411div2 D. Minimum number of steps


    D. Minimum number of steps

    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    We have a string of letters 'a' and 'b'. We want to perform some operations on it. On each step we choose one of substrings "ab" in the string and replace it with the string "bba". If we have no "ab" as a substring, our job is done. Print the minimum number of steps we should perform to make our job done modulo 109 + 7.

    The string "ab" appears as a substring if there is a letter 'b' right after the letter 'a' somewhere in the string.

    Input

    The first line contains the initial string consisting of letters 'a' and 'b' only with length from 1 to 106.

    Output

    Print the minimum number of steps modulo 109 + 7.

    Examples
    input
    ab
    output
    1
    input
    aab
    output
    3
    Note

    The first example: "ab"  →  "bba".

    The second example: "aab"  →  "abba"  →  "bbaba"  →  "bbbbaa".

    首先进行分析,有以下规则:

    1.最左方的b和最右方的a无需进行操作,也无须在意其数量

    2.每次操作时,b向前移动,a向后移动

    然后对于一段连续的aaab进行分析,可以得到一个初步的规律,如下

    aaab→ aabba→ abbaba→ abbbbaa→ bbabbbaa→ 4babbaa→ 6babaa→ 8b3a (字母前的数字代表其数量) 

    一共执行了(1+2+4)次操作,那么我们可以假定n个a移动至一个b后面进行(2^0+2^1+……+2^(n-1))次操作

    对于一段连续的abbb进行分析,可以得到一个初步的规律,如下

    abbb→bbabb → 4bab → 6ba(字母前的数字代表其数量)

    一共执行3次操作,则一个a移动至m个b后进行m次操作

    所以我们可以得出结论,将n个a移动至m个b后面进行(2^n-2)*m次操作

    令交换次数的答案为ans,且ans初值为0,n初值为0

    每遇到一个a,则ans+=n且n=n*2,每遇到一个b,则n++

    核心代码如下

    for(int i=len;i>=1;i--)
        { if(s[i]=='b')n++; else
           { ans=(ans+n)%mod; n=(n+n)%mod; } }

    不过一开始的时候走进了误区,没能直接看破规律,下面写上一些片面的分析,但也能助于理解上述代码

    结合规则1观察出一个重要的规律,那就是我们可以将每一次操作视为使一对ab换位
    现在结合以上规律对一段连续的aabb进行分析
    aabb→ abbbba → 8baa 
    这里发现最前面的b的数量并不重要,可以等价于aabb→ (+1)abbbba →(+3) bbaa  =4次

    然后中间的b也可以进行简化,只需记录b的数量

    等价于aabb→ (+1)abba → (+1 +2)bbaa  =4次

    因此每次遇到ab时,向前查询a的数量直到遇到b或边界

    然后将最靠前的a替换为b,ab中的b替换为a,若a出现n次,则增加2^n-1次操作,优化后只需向前查询一次,用一个数记录a的数量即可,这样做的问题在于2^n-1必定溢出,不过可以开一个数组,对其求模即可,时间复杂度因此比上述方法复杂一些,原代码如下

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define MAX 1000000000
    typedef long long ll;
    using namespace std;
    int a[1000005];
    void p()
    {
        for(int i=1;i<=1000005;i++)
        {
            a[i]=2*a[i-1]%(MAX+7);
        }
    }
    
    
    int main()
    {
        char c[1000005];
        int n,i,j,t,mar,k,time,mark;
        ll ans,l;
        a[0]=1;
        p();
        while(scanf("%s",&c)!=EOF)
        {
            n=strlen(c);
            ans=0,t=0,k=0;
            for(i=0;i<n;i++)
            {
                if(c[i]!='b')
                break;
                k++;
            }
            for(i=k;i<n;i++)
            {
                if(c[i]=='a')
                {
                    t++;
                }
                else
                {
                    ans+=a[t]-1;
                    ans%=(MAX+7);
                }
            }
            cout<<ans<<endl;
        }    
    }
  • 相关阅读:
    I.MX6 Parallel RGB LCD Datasheet描述
    ubuntu IP 扫描
    I.MX6 按键开关机 PMIC 检测
    java中对List中对象排序实现
    jQuery实现父窗口的问题
    如何在Oracle中复制表结构和表数据
    handsontable常规配置的中文API
    oracle中to_date详细用法示例(oracle日期格式转换)
    js中子页面父页面方法和变量相互调用
    关于Ajax的type为post提交方式出现请求失效问题
  • 原文地址:https://www.cnblogs.com/qq936584671/p/6814767.html
Copyright © 2020-2023  润新知