题目大意:
就是现在对于每一次给出的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; }