3097: Hash Killer I
Time Limit: 5 Sec Memory Limit: 128 MBSec Special Judge
Submit: 605 Solved: 228
Description
这天天气不错,hzhwcmhf神犇给VFleaKing出了一道题:
给你一个长度为N的字符串S,求有多少个不同的长度为L的子串。
子串的定义是S[l]、S[l + 1]、… S[r]这样连续的一段。
两个字符串被认为是不同的当且仅当某个位置上的字符不同。
VFleaKing一看觉得这不是Hash的裸题么!于是果断写了哈希 + 排序。
而hzhwcmhf神犇心里自然知道,这题就是后缀数组的height中 < L的个数 + 1,就是后缀自动机上代表的长度区间包含L的结点个数,就是后缀树深度为L的结点的数量。
但是hzhwcmhf神犇看了看VFleaKing的做法表示非常汗。于是想卡掉他。
VFleaKing使用的是字典序哈希,其代码大致如下:
u64 val = 0;
for (int i = 0; i < l; i++)
val = val * base + s[i] - ‘a’;
u64是无符号int64,范围是[0, 2^64)。VFleaKing让val自然溢出。
base是一个常量,VFleaKing会根据心情决定其值。
VFleaKing还求出来了base ^ l,即base的l次方,这样就能方便地求出所有长度为L的子串的哈希值。
然后VFleaKing给哈希值排序,去重,求出有多少个不同的哈希值,把这个数作为结果。
其算法的C++代码如下:
typedef unsigned long long u64;
const int MaxN = 100000;
inline int hash_handle(const char *s, const int &n, const int &l, const int &base)
{
u64 hash_pow_l = 1;
for (int i = 1; i <= l; i++)
hash_pow_l *= base;
int li_n = 0;
static u64 li[MaxN];
u64 val = 0;
for (int i = 0; i < l; i++)
val = val * base + s[i] - ‘a’;
li[li_n++] = val;
for (int i = l; i < n; i++)
{
val = val * base + s[i] - ‘a’;
val -= (s[i - l] - ‘a’) * hash_pow_l;
li[li_n++] = val;
}
sort(li, li + li_n);
li_n = unique(li, li + li_n) - li;
return li_n;
}
hzhwcmhf当然知道怎么卡啦!但是他想考考你。
Input
没有输入。
Output
你需要输出一组数据使得VFleaKing的代码WA掉。我们会使用Special Judge检查你的结果的正确性。
输出文件共两行。
第一行两个用空格隔开的数n、l。
第二行是一个长度为n的字符串。只能包含’a’~’z’。
需要保证1 <= n <= 10^5, 1 <= l <= n,
不符合以上格式会WA。
不要有多余字符,很可能导致你WA。
Sample Input
没有
Sample Output
8 4
buaabuaa
(当然这个输出是会WA的)
HINT
orz 波兰人 & fotile96 & sillycross
Source
VFleaKing & hzhwcmhf
由于此题并不是取模,而是让unsigned long long自然溢出。。
所以卡的方法非常神。。
出题人的题解:
爆u64相当于对2^64取模。
如果base是偶数的话就很好卡了,aaa……a,baaa……a,a有好多好多个,这两个字符串的hash值是相同的。

如果base是奇数的话,现在只考虑a、b两个字母。
a \ b表示a能整除b。(orz 具体数学)
设数学上的函数not(S)表示把字符串S中每个位置的’a’变成’b’,把’b’变成’a’后形成的字符串。比如not(“ababaa”) = “bababb”
strA . strB代表字符串串联。如”娃” . “哈哈” = “娃哈哈”
|str|表示字符串str的长度。
设字符串序列{orzstr[i]},orzstr[1] = “a”, orzstr[i] = orzstr[i - 1] . not(orzstr[i - 1])
那么|orzstr[i]| = |orzstr[i - 1]| * 2。显然这是等比数列,得到:|orzstr[i]| = |orzstr[1]| . 2 ^ (i - 1) = 2 ^ (i - 1)
设hash(str)为str的哈希值。
则:
hash(orzstr[i]) = hash(orzstr[i - 1]) * base ^ |not(orzstr[i - 1])| + hash(not(orzstr[i - 1]))
= hash(orzstr[i - 1]) * base ^ (2 ^ (i - 2)) + hash(not(orzstr[i - 1]))
hash(not(orzstr[i])) = hash(not(orzstr[i - 1])) * base ^ (2 ^ (i - 2)) + hash(orzstr[i - 1])
两式相减:
hash(orzstr[i]) - hash(not(orzstr[i]))
= (hash(orzstr[i - 1]) * base ^ (2 ^ (i - 2)) + hash(not(orzstr[i - 1]))) - (hash(not(orzstr[i - 1])) * base ^ (2 ^ (i - 2)) + hash(orzstr[i - 1]))
= (hash(orzstr[i - 1]) - hash(not(orzstr[i - 1]))) * (base ^ (2 ^ (i - 2)) - 1)
这让我们发现,hash(orzstr[i]) - hash(not(orzstr[i]))似乎是个神奇的东西。而我们的目的实际上是要找两个字符串strA, strB使得
hash(strA) % 2^64 = hash(strB) % 2^64
相当与
2^64 \ hash(strA) - hash(strB)
设数列{f[i]},f[i] = hash(orzstr[i]) - hash(not(orzstr[i]))
这样就有:
f[i] = f[i - 1] * (base ^ (2 ^ (i - 2)) - 1)
还是有点不爽啊……我们再设数列{g[i]},g[i] = base ^ (2 ^ (i - 1)) - 1
于是能写成:
f[i] = f[i - 1] * g[i - 1]
则f[i] = f[1] * g[1] * g[2] * … * g[i - 1]
然后发现一个神奇的事情?
base是奇数,则base的任意正整数次方也一定是奇数。所以对于任意的i必有g[i]为偶数,所以2 ^ (i - 1) \ f[i]
问题是不是结束了呢……发现没有……这样的话我们要使2 ^ 64 \ f[i],至少得让i = 65……然后发现|orzstr[65]|是个天文数字。
发现我们刚才那样分析太坑爹了……
i > 1时有:
g[i] = base ^ (2 ^ (i - 1)) - 1 = (base ^ (2 ^ (i - 2)) - 1) * (base ^ (2 ^ (i - 2)) + 1) = g[i - 1] * 一个偶数
而g[1]显然是偶数吧……
那么4 \ g[2],8 \ g[3]…
也就是说2 ^ i \ g[i]
所以f[i] 实际上有:
(2 ^ 1) * (2 ^ 2) * (2 ^ 3) * … * (2 ^ (i - 1)) \ f[i]
2 ^ (i * (i - 1) / 2) \ f[i]
当i取12时,就有66个2了哟!
这就是卡base为奇数时的方法。orzstr[12]和not(orzstr[12])即为所求。
附上本蒟蒻的代码:

#include<cstdio>
#include<cstdlib>
using namespace std;
char s[10000];
int main()
{printf("%d %d\n",(1<<11)+65,(1<<10));int now=1;s[1]='a';for (int i=1;i<=11;i++){for (int j=1;j<=now;j++) s[now+j]=s[j]=='a'?'b':'a';now<<=1;}for (int i=1;i<=now;i++) printf("%c",s[i]);for (int i=1;i<=65;i++) printf("%c",'a');printf("\n");return 0;
}

BZOJ3097Hash Killer I相关推荐

  1. linux内核oom,linux OOM killer分析

    基本概念 Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀 ...

  2. linux进程莫名其妙被kill,Linux进程突然被杀掉(OOM killer),查看系统日志

    Linux进程被杀掉(OOM killer),查看系统日志 基本概念: Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是 ...

  3. 理解和配置 Linux 下的 OOM Killer

    原文:http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/ 最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有 ...

  4. 【Android 进程保活】Low Memory Killer 机制

    文章目录 一.Low Memory Killer 机制 二.Low Memory Killer 参数 一.Low Memory Killer 机制 Android 中有一套 Low Memory Ki ...

  5. HDU 6143 Killer Names(排列+容斥,dp)

    Killer Names HDU 6143 (容斥+排列组合,dp+整数快速幂) 2017ACM暑期多校联合训练 - Team 8 1011 Killer Names 题目链接 Time Limit: ...

  6. android 刷系统,安卓10的刷机教程,教你刷好Killer的精简包

    本帖最后由 大熊花 于 2020-6-13 22:03 编辑 安卓10真香-- 之前我还退回到安卓9的公测33,心想为了玩游戏流畅,结果发现还是安卓10更好一点. 下午把东西准备齐了刷了killer的 ...

  7. (转载)Linux OOM Killer个人总结

    Linux下面有个特性叫OOM killer(Out Of Memory killer),这个东西会在系统内存耗尽的情况下跳出来,选择性的干掉一些进程以求释放一些内存.典型的情况是:某天机器突然登不上 ...

  8. (转载)Linux Out-of-Memory(OOM) Killer

    Linux有一个特性:OOM Killer,一个保护机制,用于避免在内存不足的时候不至于出现严重问题,把一些无关的进程优先杀掉,即在内存严重不足时,系统为了继续运转,内核会挑选一个进程,将其杀掉,以释 ...

  9. linux内核如何修改lowmem,技术内幕:Android对Linux内核的增强 Low Memory Killer

    6 09 2013 技术内幕:Android对Linux内核的增强 Low Memory Killer Low Memory Killer(低内存管理) 对于PC来说,内存是 至关重要.如果某个程序发 ...

  10. 认真理解 oom killer 备忘

    最近项目测试,发现一个oom killer问题,所以搜集了一些文章,理解并做记录. 现象:做性能测试时,程序自己退出,记录"killed"日志.查了下syslog发现详细记录了问题 ...

最新文章

  1. MongoDB 和 NoSQL简介
  2. .Net对SQL数据库的web备份
  3. asp.net + ajax + sqlserver 自动补全功能,asp.net+ajax+sqlserver自动补全功能实现解析
  4. TCP/ITX协议面试总结
  5. 信息学奥赛课课通VS中学生计算机,数学奥赛VS信息学奥赛 孩子们该如何选择
  6. 超全干货:数据可视化的设计总结,工具,技术要点统统都有
  7. java社区团购微信小程序源码
  8. 金庸群侠传5 自动化脚本 绝情谷大厅开宝箱按键游戏
  9. 教你快速将多个TXT文档合并成一个
  10. linux中磁盘阵列说明,常用磁盘阵列说明
  11. 【web-攻击用户】(9.3.2)诱使用户执行操作--请求伪造——UI伪装
  12. html设置网格颜色,AI网格大小颜色怎么设置-设置AI网格大小颜色的方法 - 河东软件园...
  13. 从MOSSE到KCF,再从KCF到C-COT,再从C-COT到ECO梳理
  14. LVS-NAT基于NFS存储部署Discuz
  15. 一、安装 1、kafka 需要java环境;(百度网盘地址:https://pan.baidu.com/s/1i3YXtiBH9YYvZn9vQy1g8w 提取码:dot8)
  16. 耗时10个小时用纯HTML和CSS写成的小兔鲜儿
  17. ztree树与列表名字获取
  18. 游戏场景offset坐标系关联正六边形cube坐标系
  19. ida如何识别linux内核函数,如何识别IDA反汇编中动态链接库中的函数
  20. 韩顺平JAVA-D2

热门文章

  1. 整车控制器(VCU,vehicle Controller Unit)
  2. IDEA编译错误PersistentEnumerator storage corrupted
  3. 惠普m227fdw引擎通信错误_惠普m227fdw/m132nw提示耗材余量错误解决方案
  4. 计算机视觉目标检测算法综述
  5. .NET 6 中的 Http Logging 中间件
  6. mysql批量抽取数据_批量从数据库是提取数据,并显示出来。
  7. 程序员是如何买房的?
  8. outlook怎么配置126邮箱服务器,126邮箱如何设置Microsoft Outlook的服务器?
  9. 华硕k43tk拆机清灰教程
  10. 什么是你的核心竞争力之二?