题意:给出一个n, 然后让你找到一个只包含小写字母的字符串, 并且使得这个字符串的字串正好有n个, 如果这样的字符串有多个的话, 找到字典序最小的那个输出;
思路:哇, 这个题是真的骚。。。以为是找规律。。整整三页纸的规律毛都没找到。。。然而旁边的ygay已经在爆搜了。。。后来看了看红书才知道是爆搜。。。佩服ygay的爆搜。。。。。知道爆搜之后就好做了。直接枚举所有情况。。爆搜剪枝的条件就是当前的串怎么样都达不到n就剪掉。。然后爆搜就快的飞起。。。。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
using namespace std;
string answer;
int n;
int main()
{
void slove(string str, int cur, int now);
scanf("%d", &n);
answer = "";
for (int i = 1; ; ++i) {
//cout << i << "---" << endl;
slove("", 1, i);
if (answer != "") {
cout << answer << endl;
break;
}
}
return 0;
}
void slove(string str, int cur, int now)
{
//cout << str << "---" << cur << "---" << now << endl;
if (answer != "")
return;
if (cur <= now) {
set<string> se;
for (int i = 0; i < cur - 1; ++i) {
string s = "";
for (int j = i; j < cur - 1; ++j) {
s += str[j];
se.insert(s);
}
}
int w = now - cur + 1;
if (se.size() + (w + 1) * w / 2 + w * (cur -1) < n)
return;
}
else {
set<string> se;
for (int i = 0; i < now; ++i) {
string s = "";
for (int j = i; j < now; ++j) {
s += str[j];
se.insert(s);
}
}
//cout << str << "---" << se.size() << endl;
if (se.size() == n)
answer = str;
return;
}
if (answer != "")
return;
for (int i = 1; i <= 26; ++i) {
string s = str;
s += 'a' + i - 1;
slove(s, cur + 1, now);
if (answer != "")
return;
bool flag = false;
for (int j = 0; j < cur - 1; ++j)
if (str[j] == 'a' + i - 1) {
flag = true;
break;
}
if (!flag)
return;
}
if (answer != "")
return;
}