2015-08-29 18:00:22
【传送门】
小结:开的VP,这场题目质量很高~比赛中24min过了A题就“吃面包了”。。。
第二题自己想了个很麻烦的做法... 打不完 - -,赛后补了前3题。
A题:技巧,思维。
题意:给出一个只用前p个小写英文字母的字符串,而且不存在长度>=2的回文子串,让你构造出字典序下一个这样的串(且长度不变)。串长<=1000
思路:很自然地想到给原来的串不断地+1(在p进制下)然后 n^2 判断是否符合条件,但是这样太慢。有下面更快的判断方法。
想到如果当前进位到第pos位(设最右位为第一位),1~pos-1位都没发生变化,因此1~pos-1位都不会出现回文。那么我们只需要使得第pos位和第pos-1位以及pos-2位不同即可(不形成长度为2/3的回文),因为如果能形成更长的回文,必须要使得中间部分回文,而前pos-1位并不会出现这样的情况。所以在模拟时先算出涉及进位的最高位,然后补全后面的位,方法如上述。
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; int n,p; char s[1010]; int main(){ scanf("%d%d",&n,&p); scanf("%s",s + 1); int pos = n,c = 1; while(pos >= 1){ s[pos] += c; if(s[pos] - 'a' >= p){ pos--; c = 1; } else{ if((pos > 1 && s[pos - 1] == s[pos]) || (pos > 2 && s[pos - 2] == s[pos])){ c = 1; } else{ break; } } } if(pos == 0){ printf("NO\n"); return 0; } for(int i = pos + 1; i <= n; ++i){ bool flag = false; for(int j = 0; j < p; ++j){ s[i] = j + 'a'; if(i > 1 && s[i - 1] == s[i]) continue; if(i > 2 && s[i - 2] == s[i]) continue; flag = true; break; } if(!flag){ printf("NO\n"); return 0; } } printf("%s\n",s + 1); return 0; }