USACO2012 Moo /// 模拟 oj21548

大致题意:

递归地描述序列:设S(0)为3个字符的序列“mo o”。然后在较长的序列小号ķ)通过取序列的拷贝获得小号ķ -1),则“摩... O”与ķ 2 O公司,然后该序列的另一个拷贝小号ķ -1 )。例如:

S(0)=“mo o”

S(1)=“moomooomo o”

S(2)=“moomooomoomoooomoomoo omo o”

...... 以此类推 可无限延长

预测这个字符串的第N个字符是“m”还是“o”

Input

Multiple test case. For each case:

* Line 1: A single integer N (1 ≤ N ≤ 109).

Output

For each case, output one line: The only line of output should contain a single character, which is either m or o.

Sample Input

11

Sample Output

m

#include <bits/stdc++.h>
using namespace std;
int a[35];
void constant()      /*完整序列的规律可分为 a m a 三部分
                     即moomooomoo中,moo为a部分,mooo为m部分*/
{
    a[0]=0; a[1]=3;
    for(int i=2;i<35;i++)    ///求出所有可能的有规律范围
        a[i]=a[i-1]*2+i+2;
}
int find_area(int n)
{
    int i=0;
    while(n>a[i++]);     ///找到n所在的最小的有规律范围
    return i-1;                         
}
int main()
{
    constant();
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int lie=find_area(n)-1;  ///得到在n之前的有规律范围即前面的a部分
        int flag=-1;
        while(flag<0)
        {
            n-=a[lie];            ///此时去掉前面的a部分
            if(n==1) flag=1;
            else if(n<=lie+3) flag=0;  //判断是否在m部分内
            else
            {
                n-=lie+3;        /*减去m部分,余下的后面的a部分同样可细分为a m a三部分,
                                   则再次调用find_area()得到n所在的最小规律范围*/
                lie=find_area(n)-1;             
            }
        }                         ///继续循环直到缩小到m部分 修改flag值 跳出循环
        if(flag==1) printf("m
");
        else if(flag==0) printf("o
");
    }
    
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zquzjx/p/8321124.html