洛谷 P1885 Moo

目录:


题目:

传送门


分析:

暴力模拟肯定会 T ,这里提供分治的算法。
先求出前若干个字符串的长度
将第 c 个字符串分成三部分处理:
开头的第 c 1 个字符串,中间的 m 和若干个 o ,结尾的第 c 1 个字符串。
这里为方便描述简称为开头,中间和结尾。
n 为开头第一个或中间第一个的 m 时,输出 m 并结束程序。
n 为开头第二/第三个或中间非第一个的 o 时,输出 o 并结束程序。
n 在开头的非前三个时,搜索 n 在第 c 1 个字符串的情况。
n 在结尾的非第一个时,搜索 n -前面的字符长度在第 c 1 个字符串的情况。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<stack>
#define LL long long
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}     
int len[100006],cnt;
void dfs(int q,long long n)
{
    while(len[q-1]>n) q--;
    if(n==len[q-1]+1) {printf("m");return;}
    if(n<=len[q-1]+q+2) {printf("o");return;}
    dfs(q-1,n-len[q-1]-2-q);
}
int main()
{
    long long n;
    scanf("%d",&n);
    len[0]=0;
    cnt=0;
    int i=1;
    while(1)
    {
        len[i]=2*len[i-1]+2+i;
        if(len[i]>=n) {cnt=i;break;}
        i++;
    }
    dfs(cnt,n);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35786326/article/details/81711924