CODEFORCES 645E Intellectual Inquiry

// CODEFORCES 645E Intellectual Inquiry

http://codeforces.com/problemset/problem/645/E

字母表只有前面 k 个小写字母。给出一个字符串 s,你可以往 s 后添加 n 个字母,使得,总的字符串的不同子序列最多。

Input

n k
s

1 ≤ n ≤ 1,000,000

1 ≤ k ≤ 26

1 ≤ |s| ≤ 1,000,000

Output

输出答案模 1,000,000,007。

Solution

看了题解才会的。

f[i] 表示以 i 为结尾的子序列(不含空串)有多少个,往字符串后面加一个字母 c,则只有 f[c] 会改变。而且是改成 ∑f[] + 1。重点在这个值跟 c 是没有关系的,改变之后的所以子序列数目的和是 ∑f[] - f[c] + ∑f[] + 1,要使这个值最大,应该使得 f[c] 最小,也就是说,添加一个使得 f[c] 最小的 c 在字符串末尾是最佳的方案。

Code

  1. /**


  2. * Author: +7w 

  3. */ 

  4. #include <assert.h> 

  5. #include <ctype.h> 

  6. #include <inttypes.h> 

  7. #include <math.h> 

  8. #include <stdio.h> 

  9. #include <stdlib.h> 

  10. #include <string.h> 

  11. #include <time.h> 


  12. #include <algorithm> 

  13. #include <bitset> 

  14. #include <functional> 

  15. #include <list> 

  16. #include <iostream> 

  17. #include <map> 

  18. #include <queue> 

  19. #include <set> 

  20. #include <stack> 

  21. #include <sstream> 

  22. #include <string> 

  23. #include <vector> 


  24. const int INF3 = 0x3f3f3f3f; 

  25. const int INF5 = 0x5f5f5f5f; 

  26. const double PI = acos(-1.0); 

  27. const double EPS9 = 1e-9; 

  28. const int TEN3 = 1000; 

  29. const int TEN6 = TEN3 * TEN3; 

  30. const int TEN9 = TEN6 * TEN3; 


  31. typedef long long llong; 

  32. typedef unsigned long long ullong; 

  33. typedef std::pair<int, int> pii; 


  34. #define FST first 

  35. #define SEC second 

  36. #define PB push_back 

  37. #define MP make_pair 

  38. #define CLEAR(a) memset(a, 0, sizeof(a)) 

  39. #define FILL(a, c) memset(a, c, sizeof(a)) 

  40. #define COPY(a, b) memcpy(a, b, sizeof(b)) 


  41. const int MOD = TEN9 + 7; 

  42. const int N = TEN6 + 10; 

  43. const int K = 30; 

  44. const int M = TEN6 + 10; 


  45. char str[M]; 

  46. pii cv[N]; 


  47. int main(int argc, char const *argv[]) 



  48. int n, k; 

  49. scanf("%d %d", &n, &k); 

  50. scanf("%s", str); 

  51. for (int i = 0; i < k; ++i) { 

  52. cv[i].FST = i; // cmper 

  53. cv[i].SEC = 0; // value 



  54. int sum = 0; 

  55. for (int i = 0; str[i]; ++i) { 

  56. int j = str[i] - ‘a‘; 

  57. int tmp_sec = cv[j].SEC; 

  58. cv[j].SEC = (sum + 1) % MOD; 

  59. sum = (sum - tmp_sec + MOD) % MOD; 

  60. sum = (sum + cv[j].SEC) % MOD; 

  61. cv[j].FST = i + k; 



  62. std::sort(cv, cv + k); 

  63. for (int i = 0; i < n; ++i) { 

  64. int j = i % k; 

  65. int tmp_sec = cv[j].SEC; 

  66. cv[j].SEC = (sum + 1) % MOD; 

  67. sum = (sum - tmp_sec + MOD) % MOD; 

  68. sum = (sum + cv[j].SEC) % MOD; 



  69. printf("%d\n", (sum + 1) % MOD); 

  70. return 0; 



时间: 2024-08-13 07:09:50

CODEFORCES 645E Intellectual Inquiry的相关文章

CROC 2016 - Elimination Round (Rated Unofficial Edition) E - Intellectual Inquiry dp

E - Intellectual Inquiry 思路:我自己YY了一个算本质不同子序列的方法, 发现和网上都不一样. 我们从每个点出发向其后面第一个a, b, c, d ...连一条边,那么总的不同子序列就是从0号点出发能走出多少条 不同点的路径. dp[ i ]表示是到 i 这个点的不同路径数, 构成的图显然是个DAG,把这个dp出来就好啦.最后补 n个就是贪贪心. 网上的另外两种方法. dp[ i ] 表示[1, i] 的字符串有多少不同子序列. dp[ i ] = dp[i - 1] *

E - Intellectual Inquiry

题目链接:http://codeforces.com/problemset/problem/655/E After getting kicked out of her reporting job for not knowing the alphabet, Bessie has decided to attend school at the Fillet and Eggs Eater Academy. She has been making good progress with her studi

16.05.25-16.06.10 题集

继2016.05.24续: codeforces 651B. Beautiful Paintings-简单 http://codeforces.com/problemset/problem/651/B 大意:给出一个序列,求解其任意排列中满足ai?+?1?>?ai 的元素个数最大和. 分析:理想情况下,无重复元素的0从小到大的排列,满足条件的元素个数最多,是n-1. 非理想情况下还有重复元素,只要不断提取出重复的这些元素归到另一集合再这样讨论即可. #include <iostream>

RE写作Issue问题题库分析与提纲

RE写作Issue问题题库分析与提纲 GRE写作Issue问题题库分析与提纲 第一类 社会 2. "Competition is ultimately more beneficial than detrimental to society." 归根结底,竞争对于社会是利多弊少. Generally speaking, competition contributes to progress in society. 1.        Generally speaking, competi

【codeforces 718E】E. Matvey&#39;s Birthday

题目大意&链接: http://codeforces.com/problemset/problem/718/E 给一个长为n(n<=100 000)的只包含‘a’~‘h’8个字符的字符串s.两个位置i,j(i!=j)存在一条边,当且仅当|i-j|==1或s[i]==s[j].求这个无向图的直径,以及直径数量. 题解:  命题1:任意位置之间距离不会大于15. 证明:对于任意两个位置i,j之间,其所经过每种字符不会超过2个(因为相同字符会连边),所以i,j经过节点至多为16,也就意味着边数至多

Codeforces 124A - The number of positions

题目链接:http://codeforces.com/problemset/problem/124/A Petr stands in line of n people, but he doesn't know exactly which position he occupies. He can say that there are no less than a people standing in front of him and no more than b people standing b

Codeforces 841D Leha and another game about graph - 差分

Leha plays a computer game, where is on each level is given a connected graph with n vertices and m edges. Graph can contain multiple edges, but can not contain self loops. Each vertex has an integer di, which can be equal to 0, 1 or  - 1. To pass th

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

链接: http://codeforces.com/problemset/problem/506/A 题意: 给出30000个岛,有n个宝石分布在上面,第一步到d位置,每次走的距离与上一步的差距不大于1,问走完一路最多捡到多少块宝石. 题解: 容易想到DP,dp[i][j]表示到达 i 处,现在步长为 j 时最多收集到的财富,转移也不难,cnt[i]表示 i 处的财富. dp[i+step-1] = max(dp[i+step-1],dp[i][j]+cnt[i+step+1]) dp[i+st

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store