CF 379D: New Year Letter

题目链接:

http://codeforces.com/contest/379/problem/D


题目大意:

给定一个长度为n的字符串s1和一个长度为m的字符串s2。

做k - 2次类似斐波那契的操作:sk = s(k-1) + s(k-2)。

已知sk中恰好含有k个"AC"子串,求是否存在符合条件的s1、s2


算法:

显然,除了s1和s2内部的"AC"以外,还有可能是在做连接操作的时候两字符串首位相接的拼成了"AC"。

通过简单的递推不难求出sk中包含多少个s1、s2,已经有多少种s1+s2,s2+s1,s2+s2的情况.,这个找规律也可以 


那么要计算有多少个被拼成的"AC",我们只需枚举s1和s2的第一个字母是否是'C',最后一个字母是否是'A' 
通过有多少种s1+s2,s2+s1,s2+s2的情况,可以算出有多少个"AC"是字符串首尾相接的时候拼成的
再枚举每个字符串内部有多少个“AC”,因为字符串很短,也很容易做到


这道题的算法可以说是不具备任何难度,但是貌似比赛的时候因为细节问题挂了不少人,所以在这里记录一下。

看这么简单的题写的这么长还真是无语哎。。


代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <climits>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;

long long fib[100][3][3];
int flg[3][3];
char a[200], b[200];

int main()
{
    memset(fib, 0, sizeof(fib));
    fib[1][1][0] = 1LL;
    fib[2][2][0] = 1LL;
    for(int i = 3; i <= 50; i ++)
    {
        for(int j = 1; j <= 2; j ++)
        {
            for(int k = 0; k <= 2; k ++)
            {
                fib[i][j][k] = fib[i - 1][j][k] + fib[i - 2][j][k];
            }
        }
        if(i == 3)
        {
            fib[i][1][2] ++;
        }
        else if(i & 1)
        {
            fib[i][2][2] ++;
        }
        else
        {
            fib[i][2][1] ++;
        }
    }
    int k, n, m;
    long long x;
    scanf("%d %I64d %d %d", &k, &x, &n, &m);
    if(! x)
    {
        for(int i = 0; i < n; i ++)
        {
            putchar('A');
        }
        puts("");
        for(int i = 0; i < m; i ++)
        {
            putchar('A');
        }
        puts("");
    }
    else
    {
        bool flag = true;
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        for(flg[1][1] = 0; flg[1][1] < 2 && flag; flg[1][1] ++)
        {
            for(flg[1][2] = 0; flg[1][2] < 2 && flag; flg[1][2] ++)
            {
                for(flg[2][1] = 0; flg[2][1] < 2 && flag; flg[2][1] ++)
                {
                    for(flg[2][2] = 0; flg[2][2] < 2 && flag; flg[2][2] ++)
                    {
                        int ln = n - flg[1][1] - flg[1][2];
                        int lm = m - flg[2][1] - flg[2][2];
                        for(int cot1 = 0; cot1 * 2 <= ln && flag; cot1 ++)
                        {
                            for(int cot2 = 0; cot2 * 2 <= lm && flag; cot2 ++)
                            {
                                long long tmp = cot1 * fib[k][1][0] +  cot2 * fib[k][2][0];
                                for(int fi = 1; fi <= 2; fi ++)
                                {
                                    for(int nd = 1; nd <= 2; nd ++)
                                    {
                                        if(flg[fi][1] && flg[nd][2])
                                        {
                                            tmp += fib[k][fi][nd];
                                        }
                                    }
                                }
                                if(tmp == x)
                                {
                                    flag = false;
                                    int tot1 = 0, tot2 = 0;
                                    if(flg[1][1])
                                    {
                                        a[n - 1] = 'A';
                                    }
                                    if(flg[1][2])
                                    {
                                        a[0] = 'C', tot1 = 1;
                                    }
                                    if(flg[2][1])
                                    {
                                        b[m - 1] = 'A';
                                    }
                                    if(flg[2][2])
                                    {
                                        b[0] = 'C', tot2 = 1;
                                    }
                                    for(int i = 0; i < cot1; i ++)
                                    {
                                        a[i * 2 + tot1] = 'A';
                                        a[i * 2 + tot1 + 1] = 'C';
                                    }
                                    for(int i = 0; i < cot2; i ++)
                                    {
                                        b[i * 2 + tot2] = 'A';
                                        b[i * 2 + tot2 + 1] = 'C';
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if(flag)
        {
            puts("Happy new year!");
        }
        else
        {
            for(int i = 0; i < n; i ++)
            {
                if(a[i])
                {
                    putchar(a[i]);
                }
                else
                {
                    putchar('B');
                }
            }
            puts("");
            for(int i = 0; i < m; i ++)
            {
                if(b[i])
                {
                    putchar(b[i]);
                }
                else
                {
                    putchar('B');
                }
            }
            puts("");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值