• 洛谷P1885 Moo


    题目描述

    奶牛Bessie最近在学习字符串操作,它用如下的规则逐一的构造出新的字符串:

    S(0) = “moo”

    S(1) = S(0) + “m”+ “ooo” + S(0) = “moo” + “m” + “ooo” + “moo” = “moomooomoo”

    S(2) = S(1) + “m” + “oooo” + S(1) = “moomooomoo” + “m” + “oooo” + “moomooomoo” = “moomooomoomoooomoomooomoo”

    ………

    Bessie就这样产生字符串,直到最后产生的那个字符串长度不小于读入的整数N才停止。

    通过上面观察,可以发现第k个字符串是由:第k-1个字符串 + “m” + (k+2个o) + 第k-1个字符串连接起来的。

    现在的问题是:给出一个整数N (1 <= N <= 10^9),问第N个字符是字母‘m’还是‘o’?

    输入格式

    一个整数N。

    输出格式

    一个字符,m或者o

    输入输出样例

    输入 #1
        11
    输出 #1
        m

    说明/提示

    样例解释:

    由题目所知:字符串S(0)是moo, 现在要求第11个字符,显然字符串S(0)不够长;

    同样S(1)的长度是10,也不够长;S(2)的长度是25,够长了,S(2)的第11个字符是m,所以答案就输出m。


    分治黄题(一开始啥也不会QwQ)

    一开始看到这个题没去想解决方法

    先去想的是这个字符串的长度

    于是在这里卡关了...

    建议递推重造

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<string>
    #include<cstring>
    using namespace std;
    int main()
    {
            int n;
        long long a[1000];
        memset(a,0,sizeof(a));
        a[0]=0;
        a[1]=3;
        a[2]=10;
        a[3]=25;
        cin>>n;
        for(int i=1;i<=1000;i++)
        a[i]=a[i-1]*2+i+2;
        cout<<a[n];
    }
    //求s(n)字符串的长度

    好了认真讲下思路

    首先需要判断第n个字母在哪段字符串里

    写个查找函数

    int start(int p)
    {
        int now,i=1;
        t[0] = 0;
        while(1)
        {
            t[i]=2*t[i-1]+(i+2);求字符串长度
            if(t[i]>=p)//p在s(i)这一段串里就停下
        {now=i;break;}
            i++;//不行就找下个s(i+1)
        }
        return now;//返回目前是S(几)
    }

    然后查找完以后准备分治判断

    先写一波骨架

    #include <iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define Size 100005//最大字符串组数
    using namespace std;
    typedef long long type;
    type n;
    string str;//定义字符串
    int t[Size];//定义字符串每组的长度
    int start(int p);//判断函数
    void solve(int q,int n);//处理函数
    int main()
    {
        int cnt = 0;
        cin>>n;
        cnt=start(n);//先判断
        solve(cnt,n);//再处理
        return 0;
    } 

    再写个处理函数

    void solve(int q,int n)//分别进入刚才查找出的那段字符串的序号和n
    {  
        while(t[q-1]>n)
        q--;  //从查找出的n所在的字符串的上一个字符串末尾进行查找
        if(n==t[q-1]+1)//如果n是该字符串的第一个字符
        {  
            printf("m
    "); //输出m
            return ;  
        }
        else if(n<=t[q-1]+q+2)//开始第二个直到末尾字符都为o
       {  
            printf("o
    ");
            return ;  
        }  
        solve(q-1,n-(t[q-1]+q+2));  //向内继续查找
    }

    则总代码为

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define Size 100005
    using namespace std;
    typedef long long type;
    type n;
    string str;
    int t[Size];
    int start(int p);
    void solve(int q,int n);
    int main()
    {
        int cnt = 0;
        cin>>n;
        cnt=start(n);
        solve(cnt,n);
        return 0;
    } 
    int start(int p)
    {
        int now,i=1;
        t[0] = 0;
        while(1)
        {
            t[i]=2*t[i-1]+(i+2);
            if(t[i]>=p)
            {now=i;break;}
            i++;
        }
        return now;
    }
    void solve(int q,int n)
    {  
        while(t[q-1] > n) q--;  
        if(n == t[q-1]+1)
        {  
            printf("m
    "); 
            return ;  
        }else if(n <= t[q-1]+q+2)
        {  
            printf("o
    ");
            return ;  
        }  
        solve(q-1,n-(t[q-1]+q+2));  
    }

    End

  • 相关阅读:
    C#操作ini配置文件和写入日志操作
    asp.net AJAX 定期刷新页面,然后,在 Timer 的事件中弹出窗口
    setInterval和setTimeout的区别
    检测远程URL是否存在
    SharePoint列表的模板类型中的BaseType参数和ListTemplate参数
    TCP中的Flag options
    jQuery基础教程摘录 Hello world
    SharePoint站点无法打开的问题
    SPQuery在引用field的时候要用internal name
    Windows Server 2008中用管理员的权限使用命令行来打开程序
  • 原文地址:https://www.cnblogs.com/Jiangxingchen/p/12957517.html
Copyright © 2020-2023  润新知