https://www.hackerrank.com/contests/101hack44/challenges/palindromic-subsets

如果有3个a。2个b。1个c。

每个a看成不同的,那么能选出多少个不同的回文串呢?

从回文串入手,因为回文串最多只有1种字母是奇数个。

那么,如果我能快速算区间[L, R]中各种字母出现的次数,就好了。

假设上面的数据,所得到的回文串是:

a取奇数个:2^2 * 2^1(b只能取偶数个) * 2^0(C是偶数个,这个时候是空集)

然后再枚举b取奇数个,其他取偶数个。

最后,还有一种情况,就是全部都是偶数个,这个时候因为可能选到的全部都是空集,所以最后结果要减去1.

接下来就是快速计算了。明显线段树,一开始不知道怎么维护区间,

其实区间更新,很简单,因为字母的数量是不会变的,对于区间存在2个a的话,反转1次,就只是2个b。

所以只需要枚举26个字母,cnt[(i + k) % 26] = cnt[i]

意思是产生这个字母的个数是有它来产生的。然后线段树更新即可。

线段树写了很多次,看模板才想起怎么lazy--update 苦逼。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <assert.h>
  7. #define IOS ios::sync_with_stdio(false)
  8. using namespace std;
  9. #define inf (0x3f3f3f3f)
  10. typedef long long int LL;
  11.  
  12. #include <iostream>
  13. #include <sstream>
  14. #include <vector>
  15. #include <set>
  16. #include <map>
  17. #include <queue>
  18. #include <string>
  19. #define root 1, n, 1
  20. #define lson L, mid, cur << 1
  21. #define rson mid + 1, R, cur << 1 | 1
  22.  
  23. const int maxn = 1e5 + ;
  24. char str[maxn];
  25. const int MOD = 1e9 + ;
  26. char to[];
  27. int add[maxn << ];
  28. LL quick_pow(LL a, LL b, int MOD) {
  29. LL ans = ;
  30. assert(b >= );
  31. while (b) {
  32. if (b & ) {
  33. ans = ans * a;
  34. if (ans >= MOD) ans %= MOD;
  35. }
  36. b >>= ;
  37. a *= a;
  38. if (a >= MOD) a %= MOD;
  39. }
  40. return ans;
  41. }
  42. struct node {
  43. int cnt[ + ];
  44. } seg[maxn << ];
  45. void toget(struct node &a, int val) {
  46. int cnt[ + ] = {};
  47. for (int i = ; i < ; ++i) {
  48. cnt[i] = a.cnt[i];
  49. }
  50. for (int i = ; i < ; ++i) {
  51. a.cnt[(i + val) % ] = cnt[i];
  52. }
  53. return;
  54. }
  55. void pushUp(int cur) {
  56. for (int i = ; i < ; ++i) {
  57. seg[cur].cnt[i] = seg[cur << ].cnt[i] + seg[cur << | ].cnt[i];
  58. }
  59. }
  60. void pushDown(int cur) {
  61. if (add[cur]) {
  62. add[cur << | ] += add[cur];
  63. add[cur << | ] %= ;
  64. add[cur << ] += add[cur];
  65. add[cur << ] %= ;
  66. toget(seg[cur << ], add[cur]);
  67. toget(seg[cur << | ], add[cur]);
  68. add[cur] = ;
  69. }
  70. }
  71. void build(int L, int R, int cur) {
  72. if (L == R) {
  73. seg[cur].cnt[str[L] - 'a'] = ;
  74. return;
  75. }
  76. int mid = (L + R) >> ;
  77. build(lson);
  78. build(rson);
  79. pushUp(cur);
  80. }
  81. void upDate(int be, int en, int val, int L, int R, int cur) {
  82. if (L >= be && R <= en) {
  83. toget(seg[cur], val);
  84. add[cur] += val;
  85. add[cur] %= ;
  86. return;
  87. }
  88. pushDown(cur);
  89. int mid = (L + R) >> ;
  90. if (mid >= be) upDate(be, en, val, lson);
  91. if (mid < en) upDate(be, en, val, rson);
  92. pushUp(cur);
  93. }
  94. int query(int be, int en, int ch, int L, int R, int cur) {
  95. if (L >= be && R <= en) {
  96. return seg[cur].cnt[ch];
  97. }
  98. pushDown(cur);
  99. int mid = (L + R) >> ;
  100. int lans = , rans = ;
  101. if (mid >= be) lans = query(be, en, ch, lson);
  102. if (mid < en) rans = query(be, en, ch, rson);
  103. return lans + rans;
  104. }
  105. void work() {
  106. for (int i = 'a'; i <= 'z' - ; ++i) {
  107. to[i] = i + ;
  108. }
  109. to['z'] = 'a';
  110. int n, q;
  111. scanf("%d%d", &n, &q);
  112. scanf("%s", str + );
  113. build(root);
  114. while (q--) {
  115. int flag, L, R;
  116. scanf("%d", &flag);
  117. if (flag == ) {
  118. scanf("%d%d", &L, &R);
  119. L++;
  120. R++;
  121. LL ans = ;
  122. int len = ;
  123. for (int i = ; i < ; ++i) {
  124. int ret = query(L, R, i, root);
  125. if (ret > ) len++;
  126. else continue;
  127. ans = ans * quick_pow(, ret - , MOD);
  128. if (ans >= MOD) ans %= MOD;
  129. }
  130. ans *= (len + );
  131. ans %= MOD;
  132. ans = (ans - + MOD) % MOD;
  133. cout << ans << endl;
  134. } else {
  135. int t;
  136. scanf("%d%d%d", &L, &R, &t);
  137. L++;
  138. R++;
  139. upDate(L, R, t % , root);
  140. // printf("%d****\n", query(3, 3, 'u' - 'a', root));
  141. }
  142. }
  143. // cout << query(1, n, 'o' - 'a', root) << endl;
  144. }
  145.  
  146. int main() {
  147. #ifdef local
  148. freopen("data.txt", "r", stdin);
  149. // freopen("data.txt", "w", stdout);
  150. #endif
  151. work();
  152. return ;
  153. }

Palindromic Subsets 数学 + 线段树的更多相关文章

  1. Codeforces 311D Interval Cubing 数学 + 线段树 (看题解)

    Interval Cubing 这种数学题谁顶得住啊. 因为 (3 ^ 48) % (mod - 1)为 1 , 所以48个一个循环节, 用线段树直接维护. #include<bits/stdc ...

  2. 2017ICPC北京赛区网络赛 Minimum(数学+线段树)

    描述 You are given a list of integers a0, a1, …, a2^k-1. You need to support two types of queries: 1. ...

  3. [CSP-S模拟测试]:最大值(数学+线段树)

    题目背景 $Maxtir$最喜欢最大值. 题目传送门(内部题128) 输入格式 第$1$行输入四个正整数$n,m,q$. 第$2$至$n+1$行中,第$i+1$行输入魔法晶石$i$的三种属性$(x_i ...

  4. [CSP-S模拟测试]:旅行(数学+线段树)

    题目传送门(内部题12) 输入格式 第一行,一个整数$n$,代表树的点数.第二行,$n$个整数,第$i$个整数是$B_i$,描述排列$B$.接下来$n−1$行,每行两个整数$u,v$,描述一条树边$( ...

  5. Sasha and a Very Easy Test CodeForces - 1109E (数学,线段树)

    大意: 给定n元素序列, q个操作: (1)区间乘 (2)单点除(保证整除) (3)区间求和对m取模 要求回答所有操作(3)的结果 主要是除法难办, 假设单点除$x$, $x$中与$m$互素的素因子可 ...

  6. BZOJ 5334--[Tjoi2018]数学计算(线段树)

    5334: [Tjoi2018]数学计算 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 220  Solved: 147[Submit][Status ...

  7. 【BZOJ5334】数学计算(线段树)

    [BZOJ5334]数学计算(线段树) 题面 BZOJ 洛谷 题解 简单的线段树模板题??? 咕咕咕. #include<iostream> #include<cstdio> ...

  8. codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)

    In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...

  9. 【线段树/数学/扩展欧几里得】 Bzoj 3913:奇数国

    Description 在一片美丽的大陆上有100000个国家,记为1到100000.这里经济发达,有数不尽的账房,并且每个国家有一个银行.某大公司的领袖在这100000个银行开户时都存了3大洋,他惜 ...

随机推荐

  1. win8系统 如何不显示这台电脑的文件夹

    在win8系统中,默认有下面这种文件夹   只要打开注册表编辑器,找到下面所示的项目,删除所有子文件夹即可(最后剩下一个DelegateFolders不用管) [HKEY_LOCAL_MACHINE\ ...

  2. axis client tomcat jsp调用最少jar

    tomcat调用和main方法调用不同在于引入的jar不一样.tomcat引入的jar是全部lib以下的jar包,main是project引入的jar.假设直接进行公布lib下的全部jar都会引入到p ...

  3. C#调用国家气象局天气预报接口

    原文:C#调用国家气象局天气预报接口 一.需求 最近,刚好项目中有天气预报查询功能的需求,要求录入城市名称,获取该城市今日天气信息及相关气象生活辅助信息等. 例如:查询北京市天气 结果为: 今日北京天 ...

  4. HDU 1824 Let&#39;s go home (2-SAT判定)

    Let's go home Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  5. 单片机远程控制步进电机、LED灯和蜂鸣器

    通过採用C#语言实现的上位机控制单片机的步进电机模块.LED灯和蜂鸣器模块,使步进电机进行正.反转和停止并控制转速:LED灯模块进行有选择的呼吸式表达:蜂鸣器模块的開始和终止. 上位机通过串口和自己定 ...

  6. 再理解HDFS的存储机制

    再理解HDFS的存储机制 1. HDFS开创性地设计出一套文件存储方式.即对文件切割后分别存放: 2. HDFS将要存储的大文件进行切割,切割后存放在既定的存储块(Block)中,并通过预先设定的优化 ...

  7. excel 学习

    最近越來越感覺到熟練運用office軟件是一門很深的學問,以前一直忽視了這個技能,因爲從來都不覺得這個有什麼技術難度.正是因爲這樣想,所以才一直沒能去好好研究使用這套工具.現在卻覺得有必要學習,在於: ...

  8. 数据库建表参考(SQL Server)

      (1).字段设置为Not Null+Default Value.原因:减少三值判断,可为Null的字段要多判断null:另外,定长字段为null也占空间,变长字段为空字符串也是不占空间,所以设置成 ...

  9. dotnet new 命令

    如果想知道这个命令的详细用法,可以在打完命令之后,在输入一个" --help"即可 $ dotnet new --help.NET Initializer Usage: dotne ...

  10. Python开发【第2节】【Python运算符】

    Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算符 成员运算符 身份运算符 运算符优先级 1.算术运算符 假设变量a = 10,变量b = 21: ...