【NOIP模拟题】【暴力求解法】【JOI】2016.11.14第二题 愉快的logo设计 题解

愉快的logo设计(B.c/cpp/pas/in/out)
(Time Limit:1s Memory Limit:256MB)
【Description】
K理事长正在思考日本信息学奥林匹克竞赛选手的应援道具的logo问题。某天,K理事长突发奇想,想要设计一个用’J’,’O’,’I’三种文字环形排列的logo,意为希望选手能从JOI中收获快乐的意思。
(注:“环形地”在日文中的表述为“円状に”,“円”读作“en”,再加上“JOI”三个字即为“enjoy”„„)
如下所示,对于任意非负整数k,我们定义标号为k的JOI序列Sk为:
·S0为’J’,’O’,’I’中任一字符构成的长度为1的字符串
·S[k+1]为最初4^k个字符都是’J’,接下来的4^k个字符都是’O’,接下来的4^k个字符都是’I’,最后4^k个字符是字符串Sk的长为4^(k+1)的字符串
现在,K理事长在纸上写下了由4^K个文字构成的一个环形字符串,字符串中每个字符都是’J’,’O’,’I’中的一个。K理事长想要修改一些文字,使得得到的字符串从某个起点开始顺时针读一圈后可以得到SK。在满足条件的情况下,要求修改的文字数量最少。
【Input】
第一行一个正整数K,表示K理事长在纸上写下了一个长度为4^K的环状字符串。
第二行一个由’J’,’O’,’I’三个字符构成的长为4^K的字符串,表示纸上的环形字符串从某个起点出发顺时针阅读一圈得到的字符串。
【Output】
输出一行一个整数,表示修改文字数量的最小值。
【Sample Input】
2
JJOIJJOJOIOJOOOI
【Sample Output】
7
【HINT】
这里写图片描述
从○标记的位置顺时针阅读一圈得到“JJJJOOOOIIIIJOIJ”,满足S2的条件,且修改文字数达到最小值7。
【Data Constraint】
对于30%的数据,1<=K<=5
对于100%的数据,1<=K<=10

我们的所求的那个字符串是几乎确定的,那么我们就改变开头来暴力搞他。(30%)
记录J、O、I的前缀和,再暴力。(100%)

附代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#define LL long long
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif

using namespace std; 

const int maxxx = 1048580;
int k,len,tot=1e9+7;
int J[maxxx*2],O[maxxx*2],I[maxxx*2],f[12];
char a[maxxx*2];

template <class T> inline void read(T &xx)
{
    xx = 0;
    T flag = 1;
    char ch = (char)getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch == '-') flag = -1;
        ch = (char)getchar();
    }
    while(ch>='0' && ch<='9')
    {
        xx = (xx<<1) + (xx<<3) + ch - '0';
        ch = (char)getchar();
    }
    xx *= flag;
}

void init()
{
    read(k);
    scanf("%s",a);
    len = strlen(a);
    for (int i = len; i <= len*2-1; i++) a[i] = a[i-len];
    len = strlen(a);
}

void work()
{
    f[0] = 1;
    for(int i = 1; i <= 10; i++)
        f[i] = f[i-1] * 4;
    for(int i = 0; i < len; i++)
    {
        J[i] += J[i-1];
        O[i] += O[i-1];
        I[i] += i[I-1];
        if(a[i] == 'J') J[i]++;
        if(a[i] == 'O') O[i]++;
        if(a[i] == 'I') I[i]++;
    }
    for(int i=0;i<len/2;i++)                
    {
        int ans = 1, h = i;                 
        for(int j = k - 1; j >= 0; j--)
        {
            for(int s = 0; s <= 2; s++)     
            {
                if(h != 0)
                {
                    if(s == 0) ans += J[h+f[j]-1] - J[h-1];
                    if(s == 1) ans += O[h+f[j]-1] - O[h-1];
                    if(s == 2) ans += I[h+f[j]-1] - I[h-1];
                    h += f[j];
                }
                else
                {
                    if(s == 0) ans += J[h+f[j]-1];
                    if(s == 1) ans += O[h+f[j]-1];
                    if(s == 2) ans += I[h+f[j]-1];
                    h += f[j];
                }
            }
        }
        tot = min(tot, len/2-ans);
    }
}

int main()
{
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    init();
    work();
    printf("%d",tot);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值