1. 程式人生 > >HDU 4850 Wow! Such String! 歐拉回路

HDU 4850 Wow! Such String! 歐拉回路

題目大意:

就是現在對於每一次給出的N <= 50W, 構造一個長度為N的串只包含小寫字母且每一個長度>=4的子串都只出現一次

如果不可能就輸出Impossible

大致思路:

首先考慮到如果長度為l + 1的串出現了兩次那麼長度為l的串一定也出現了兩次

所以構造的串一定是所有長度為四的串都只出現了一次

那麼能不能對於所有的長度為4的串都出現呢

一共有26*26*26*26種可能的長度為4的子串

我們從狀態轉移的角度進行考慮

考慮4個字母的串, 在後面沒加上一個字元, 就變成另外4個字母組成的串結尾的狀態

例如aaaa結尾通過新增字元b變成aaab結尾再新增c變成aabc結尾

那麼對於每一個長度為4的串一共有26種可能的轉移

於是我們可以得到一個26*26*26*26個點的有向圖的轉移, 每個點有26個出邊26個入邊, 於是這個圖一定存在歐拉回路, 那麼我們從任意一個點開始一定能找到一條路徑走過每個點恰好一次

於是得出結論:這個串最大長度是26*26*26*26 + 3, 對於大於這個長度的N直接判Impossible否則輸出前N個字元即可

程式碼如下:

Result  :  Accepted     Memory  :  15556 KB     Time  :  187 ms

/*
 * Author: Gatevin
 * Created Time:  2015/10/6 12:57:29
 * File Name: Sakura_Chiyo.cpp
 */
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

char s[500010];
char res[500010];
const int m1 = 26, m2 = 26*26, m3 = 26*26*26;
bool vis[26*26*26*26];
int result = -1;
const int maxn = 26*26*26*26;

bool dfs(int now, int dep)
{
    //vis[now] = 1;
    if(dep == maxn)
    {
        for(int i = 0; i < dep + 3; i++)
            res[i] = s[i];
        result = dep;
        return true;
    }
    int p0 = now / m3;
    int p1 = (now % m3) / m2;
    int p2 = (now % m2) / m1;
    int p3 = (now % m1);
    for(int i = 0; i < 26; i++)
    {
        int nex = p1*m3 + p2*m2 + p3*m1 + i;
        if(!vis[nex])
        {
            s[dep + 3] = 'a' + i;
            vis[nex] = 1;
            if(dfs(nex, dep + 1))
                return true;
            vis[nex] = 0;
        }
    }
    return false;
}

int main()
{
    s[0] = 'a';
    s[1] = 'a';
    s[2] = 'a';
    s[3] = 'a';
    vis[0] = 1;
    dfs(0, 1);
    int N;
    while(~scanf("%d", &N))
    {
        if(N > maxn + 3)
        {
            puts("Impossible");
            continue;
        }
        else for(int i = 0; i < N; i++)
            putchar(res[i]);
        putchar('\n');
    }
    return 0;
}