Ural 2037 Richness of binary words

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=2037


题意:给一个n,对于每个i∈[1,n],都给出一个字符串si,si仅由字符'a'和'b'组成,长度为n且含有i个不同的回文子串,若无输出NO。


思路:没找到什么好思路,只能打表找规律。然后我们可以发现,n<=7,只有i等于n,si才存在;n等于8时,i从[7-8]存在si;n>=9,i从[8,n]存在。

对于n>=9,打表找规律。会发现是由三部分组成:

①i==n,全部构造成‘a’即可。

②从i=n-1开始记做第一个,此时应构造成左边两个'a',中间是bbab,右边全部填充'a'

随着i每次减少,左边的a多一个,右边的a少一个,直到左边的a的个数超过右边的a的个数(可以相等)。

③i==8时记做第一个,此时一个循环节为bbab+2个'a',从右往左放,直至长度为n为止。随着i增大,'a'的个数加1。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))

int n;

//int temp[20];
//bool check(int st,int len)
//{
//    int p = st;
//    int q = st+len-1;
//    while( p < q )
//    {
//        if ( temp[p] != temp[q] ) return false;
//        p++ , q--;
//    }
//    return true;
//}
//string f( int st , int len )
//{
//    string ans = "";
//    rep(i,1,len)
//    {
//        ans = ans + (char)(temp[st]+'0');
//        st++;
//    }
//    return ans;
//}
//void init()
//{
//    bool flag[20];
//    Clean(flag,false);
//    Clean(temp,0);
//    map<string,int> a;
//    rep(i,0,(1<<n )- 1)
//    {
        if ( i == (1<<n )- 1 )
            puts("");
//        int ttt = i;
//        int L = 0;
//        while(ttt)
//        {
//            temp[++L] = ttt % 2;
//            ttt >>= 1;
//        }
//        a.clear();
//        int x = 0;
//        rep(len,1,n)
//        rep(i,1,n-len+1)
//        if ( check(i,len) )
//        {
//            string num = f(i,len);
//            if ( a[num] == 0 ) x++,a[num] = 1;
//        }
//        if ( x < n && !flag[x] )
//        {
//            flag[x] = true;
//            printf("%d:\n",x);
//            rep(i,1,n) cout<<temp[i];
//            puts("");
//        }
        printf("%d:\n",x);
        rep(i,1,n) cout<<temp[i];
            puts("");
//    }
//    puts("");
//}

void puta(int k)
{
    rep(i,1,k) putchar('a');
}

void putb(int k)
{
    rep(i,1,k) putchar('b');
}

int main()
{
//    while( cin>>n )
//    {
//        if ( n == 0 ) break;
//        init();
//    }
    //注释部分为粗糙的打表
    int n;
    cin>>n;
    rep(i,1,n)
    {
        printf("%d : ",i);
        if ( i <= 6 && i != n )
            puts("NO");
        else if ( i == n )
        {
            puta(n);
            puts("");
        }
        else if ( i == 7 )
        {
            if ( n == 8 )
                puts("aabbabaa");
            else puts("NO");
        }
        else  //上面是特殊情况。
        {
            int l = n + 1 - i;  //第二种情况
            int r = n - 4 - l;
            if ( l <= r )
            {
                puta(l);
                printf("bbab");
                puta(r);
                puts("");
            }
            else //第三种情况
            {
                int z = i - 8 + 2; //后面+'a'的个数
                int len = 4 + z; //一个循环的长度
                int ret = n % len; //最左边不完整循环的长度
                if ( ret ==  z + 4 )
                    printf("bbab");
                else if ( ret ==  z + 3 )
                    printf("bab");
                else if ( ret ==  z + 2 )
                    printf("ab");
                else if ( ret ==  z + 1 )
                    printf("b");
                if (ret) puta( min( z,ret) ); //输出不完整循环部分
                len = n/len;
                rep(i,1,len) //输出完整循环部分
                {
                    printf("bbab");
                    puta(z);
                }
                puts("");
            }
        }
    }
    return 0;
}




评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值