记录编号 146723 评测结果 AAAAAAAAAA
题目名称 [SRM 467] 均匀字符串 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.046 s
提交时间 2015-01-19 11:05:40 内存使用 58.69 MiB
显示代码纯文本
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<vector>
  6. using namespace std;
  7. const int HSIZE=50007;
  8. typedef unsigned US;
  9. typedef long long LL;
  10. typedef long double LDB;
  11. //我们用一个unsigned去表示一个状态,每四个bit一位
  12. int n,d;//相邻n位中不同的不能超过d种
  13. class Node{
  14. public:
  15. unsigned s;
  16. LDB f;
  17. int nxt;
  18. };
  19. class Hash_Map{
  20. public:
  21. int head[HSIZE];
  22. Node lis[HSIZE];
  23. int tot;
  24. LDB& operator [] (unsigned s){
  25. int key=s%HSIZE,x;
  26. for(x=head[key];x;x=lis[x].nxt){
  27. if(lis[x].s==s) return lis[x].f;
  28. }
  29. lis[++tot]=(Node){s,-1,head[key]};//-1代表它不存在
  30. head[key]=tot;
  31. return lis[tot].f;
  32. }
  33. };
  34. Hash_Map F[51];
  35. unsigned re_label(unsigned s){
  36. static int lis[10];
  37. memset(lis,0,sizeof(lis));
  38. int ans=0,tot=0;
  39. for(int i=0;i<32;i+=4){
  40. int t=(s>>i)&15;
  41. if(!t) break;
  42. if(!lis[t]) lis[t]=++tot;
  43. ans|=(lis[t]<<i);
  44. }
  45. return ans;
  46. }
  47. void calc_len(unsigned s,unsigned &len,unsigned &mx){
  48. len=mx=0;
  49. for(int i=0;i<32;i+=4){
  50. unsigned t=(s>>i)&15;
  51. if(!t) break;
  52. len++,mx=max(mx,t);
  53. }
  54. }
  55. LDB DP(unsigned s,int len){//在s之后还要走len位
  56. s=re_label(s);
  57. LDB &ans=F[len][s];
  58. if(ans>=0) return ans;
  59. ans=0;
  60. unsigned m,mx;
  61. calc_len(s,m,mx);
  62. if(mx>d) return ans=0;
  63. if(len==0) return ans=1;
  64. //考虑加上一个新的
  65. if(mx<d){
  66. if(m<n-1) ans+=(26-mx)*DP(s|((mx+1)<<m*4),len-1);
  67. else ans+=(26-mx)*DP((s>>4)|((mx+1)<<(n-2)*4),len-1);
  68. }
  69. //考虑用一个旧的
  70. for(unsigned i=1;i<=mx;i++){
  71. if(m<n-1) ans+=DP(s|(i<<m*4),len-1);
  72. else ans+=DP((s>>4)|(i<<(n-2)*4),len-1);
  73. }
  74. return ans;
  75. }
  76. unsigned turn_US(string &str){//若过长则只取后n-1位
  77. static int lis[26];
  78. int tot=0;
  79. memset(lis,0,sizeof(lis));
  80. int m=str.size(),start=max(0,m-(n-1));
  81. unsigned ans=0;
  82. for(int i=0;i<m-start;i++){
  83. int c=str[i+start]-'a';
  84. if(!lis[c]) lis[c]=++tot;
  85. ans|=(lis[c]<<i*4);
  86. }
  87. return ans;
  88. }
  89. bool check_legal(string &str){//检查一个字符串是否合法
  90. static int cnt[26];
  91. memset(cnt,0,sizeof(cnt));
  92. int now=0;
  93. for(int i=0;i<str.size();i++){
  94. int c=str[i]-'a';
  95. if(cnt[c]==0) now++;
  96. cnt[c]++;
  97. if(i>=n){
  98. c=str[i-n]-'a';
  99. cnt[c]--;
  100. if(cnt[c]==0) now--;
  101. }
  102. if(now>d) return false;
  103. }
  104. return true;
  105. }
  106. LDB calc(string str,int len){//以str为前缀,str后面还有len位的合法字符串数量
  107. if(!check_legal(str)) return 0;//如果str本身不合法
  108. unsigned s=turn_US(str);
  109. return DP(s,len);
  110. }
  111. LDB calc_less(string seed,int L){
  112. string now="";
  113. LDB ans=0;
  114. for(int i=0;i<L;i++){
  115. for(char c='a';c<seed[i];c++){
  116. ans+=calc(now+c,L-1-i);
  117. }
  118. now+=seed[i];
  119. if(!check_legal(now)) break;//这里测试时得取n位
  120. while(now.size()>=n) now.erase(now.begin());
  121. }
  122. return ans;
  123. }
  124. class NextHomogeneousStrings{
  125. public:
  126. string getNext(int d_,int n_,string seed,LL K){
  127. K++;
  128. //找>=seed且第K小的字符串
  129. d=d_,n=n_;
  130. int L=seed.size();
  131. string ans;
  132. int left;
  133. for(int i=L-1;i>=0;i--){//试图在第i位上进行更改
  134. char low=(i==L-1?seed[i]:seed[i]+1);
  135. for(char c=low;c<='z';c++){
  136. LDB now=calc(seed.substr(0,i)+c,L-1-i);
  137. if(now<K) K-=now;
  138. else{
  139. ans=seed.substr(0,i)+c,left=L-1-i;
  140. goto OUT;
  141. }
  142. }
  143. }
  144. return "";
  145. OUT:;
  146. //现在我们需要取以ans为前缀的第K小字符串
  147. for(int i=1;i<=left;i++){
  148. for(char c='a';c<='z';c++){
  149. LDB now=calc(ans+c,left-i);
  150. if(now<K) K-=now;
  151. else{
  152. ans+=c;
  153. break;
  154. }
  155. }
  156. }
  157. return ans;
  158. }
  159. };
  160. int main(){
  161. freopen("homogeneous.in","r",stdin);
  162. freopen("homogeneous.out","w",stdout);
  163. NextHomogeneousStrings me;
  164. int d,n;
  165. LL k;
  166. string seed;
  167. cin>>d>>n>>seed>>k;
  168. cout<<me.getNext(d,n,seed,k)<<endl;
  169. //cout<<me.getNext(1,2,"aaa",3)<<endl;
  170. return 0;
  171. }