CodeForces 820C

题意略。

这道题目的出题者竟然被hack了!?

我的思路是:在游戏开始时,为了尽量少地用字母,我应该尽量选取计算机输出的前a个字母中已经使用过的字母。但是为了使电脑也尽量少用字母,我添加的这b个字母应该是一样的,

这样我才能给电脑留出更多的使用已经出现过的字母的空间。

假设现在计算机已经走完了它的一步,现在轮到我了,现在字符串总长度为i。

当a > b时,我添加字母的范围是[i - (a - b) + 1,i]这(a - b)个字母(连续添加b个一样的),这样可以发现出现了长度为2 * (a + b)的循环节,我们把这(a - b)种循环节构造出来,储存在数组中。

当a > b时,我只用添加b个str[i]这个字符就行了。这样它的循环节也是2 * (a + b)的。

详见代码:

#include<bits/stdc++.h>
#define maxn 100
using namespace std;

char str[30][maxn];
int visit[maxn];
int len,tot,kind,a,b,l,r;

void prepare(){
    tot = (a <= b ? a + 1 : 2 * a - b);
    len = ((a + b)<<1);
    if(b >= a){
        kind = 1;
        for(int i = 1;i <= a;++i) str[1][i] = 'a' + i - 1;
        for(int i = a + 1;i <= a + b;++i) str[1][i] = str[1][a];
        for(int i = a + b;i > b;--i) visit[str[1][i] - 'a'] = 1;
        for(int i = a + b + 1,j = 0;i <= 2 * a + b;++i){
            while(visit[j]) ++j;
            str[1][i] = 'a' + j;
            visit[j] = 1;
        }
        for(int i = a + b + a + 1;i <= a + b + a + b;++i)
           str[1][i] = str[1][a + b + a];
        for(int i = 2 * (a + b) + 1;i <= 4 * (a + b);++i)
            str[1][i] = str[1][i - 2 * (a + b)];
        str[1][4 * (a + b) + 1] = '';
       }
       else{
           kind = a - b;
           for(int k = 1;k <= a - b;++k){
               memset(visit,0,sizeof(visit));
               for(int i = 1;i <= a;++i) str[k][i] = 'a' + i - 1;
            for(int i = a + 1;i <= a + b;++i) str[k][i] = str[k][k + b];
            for(int i = a + b;i > b;--i) visit[str[k][i] - 'a'] = 1;
            for(int i = a + b + 1,j = 0;i <= 2 * a + b;++i){
                while(visit[j]) ++j;
                str[k][i] = 'a' + j;
                visit[j] = 1;
            }
            for(int i = a + b + a + 1;i <= a + b + a + b;++i)
                str[k][i] = str[k][a + b + a];
            for(int i = 2 * (a + b) + 1;i <= 4 * (a + b);++i)
                str[k][i] = str[k][i - 2 * (a + b)];
            str[k][4 * (a + b) + 1] = '';
        }
    }
}

int main(){
    scanf("%d%d%d%d",&a,&b,&l,&r);
    prepare();
    if(r - l >= len) printf("%d
",tot);
    else{
        r = (r - 1) % len + 1;
        l = (l - 1) % len + 1;
        if(r < l) r += len;
        int ans = maxn;
        memset(visit,0,sizeof(visit));
        for(int k = 1;k <= kind;++k){
            int temp = 0;
            memset(visit,0,sizeof(visit));
            for(int i = l;i <= r;++i){
                if(visit[str[k][i] - 'a'] == 0){
                    ++temp;
                    visit[str[k][i] - 'a'] = 1;
                }
            }
            ans = min(temp,ans);
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tiberius/p/8472529.html