bzoj3097: Hash Killer I

35 篇文章 0 订阅
3 篇文章 0 订阅

题目
题解

Solution

如果 b a s e base base是偶数,那么 a . . . . . . . . . a a a ( > 64 a.........aaa(>64 a.........aaa(>64 a ) a) a) b a . . . . . . . a a ( a ba.......aa(a ba.......aa(a的数量为前面那么串 a a a的数量 − 1 ) -1) 1),这两个串长度相同, h a s h hash hash值相同,显然串是不同的,这样就卡掉了。
如果 b a s e base base是奇数,就比较麻烦了。
v f k vfk vfk的做法吧:
如果 b a s e base base是奇数的话,现在只考虑 a a a b b b两个字母。
a ∣ b a|b ab表示 a a a能整除 b b b。( o r z orz orz具体数学)
设数学上的函数 n o t ( S ) not(S) not(S)表示把字符串 S S S中每个位置的 ′ a ′ 'a' a变成 ′ b ′ 'b' b,把 ′ b ′ 'b' b变成 ′ a ′ 'a' a后形成的字符串。
s t r A . s t r B strA.strB strA.strB代表字符串串联。
∣ s t r ∣ |str| str表示字符串 s t r str str的长度。
设字符串序列 o r z s t r [ i ] {orzstr[i]} orzstr[i] o r z s t r [ 1 ] = " a " , o r z s t r [ i ] = o r z s t r [ i − 1 ] . n o t ( o r z s t r [ i − 1 ] ) orzstr[1]="a",orzstr[i]=orzstr[i-1].not(orzstr[i-1]) orzstr[1]="a",orzstr[i]=orzstr[i1].not(orzstr[i1])
那么 ∣ o r z s t r [ i ] ∣ = ∣ o r z s t r [ i − 1 ] ∣ ∗ 2 |orzstr[i]|=|orzstr[i-1]|*2 orzstr[i]=orzstr[i1]2。显然这是等比数列,得到: ∣ o r z s t r [ i ] ∣ = ∣ o r z s t r [ 1 ] ∣ . 2 i − 1 = 2 i − 1 |orzstr[i]|=|orzstr[1]|.2^{i-1}=2^{i-1} orzstr[i]=orzstr[1].2i1=2i1
h a s h ( s t r ) hash(str) hash(str) s t r str str的哈希值。
则:
h a s h ( o r z s t r [ i ] ) = h a s h ( o r z s t r [ i − 1 ] ) ∗ b a s e ∣ n o t ( o r z s t r [ i − 1 ] ) ∣ + h a s h ( n o t ( o r z s t r [ i − 1 ] ) ) hash(orzstr[i])=hash(orzstr[i-1])*base^|not(orzstr[i-1])|+hash(not(orzstr[i-1])) hash(orzstr[i])=hash(orzstr[i1])basenot(orzstr[i1])+hash(not(orzstr[i1]))
= h a s h ( o r z s t r [ i − 1 ] ) ∗ b a s e 2 i − 2 + h a s h ( n o t ( o r z s t r [ i − 1 ] ) ) =hash(orzstr[i-1])*base^{2^{i-2}}+hash(not(orzstr[i-1])) =hash(orzstr[i1])base2i2+hash(not(orzstr[i1]))
h a s h ( n o t ( o r z s t r [ i ] ) ) = h a s h ( n o t ( o r z s t r [ i − 1 ] ) ) ∗ b a s e 2 i − 2 + h a s h ( o r z s t r [ i − 1 ] ) hash(not(orzstr[i]))=hash(not(orzstr[i-1]))*base^{2^{i-2}}+hash(orzstr[i-1]) hash(not(orzstr[i]))=hash(not(orzstr[i1]))base2i2+hash(orzstr[i1])
两式相减:
h a s h ( o r z s t r [ i ] ) − h a s h ( n o t ( o r z s t r [ i ] ) ) hash(orzstr[i])-hash(not(orzstr[i])) hash(orzstr[i])hash(not(orzstr[i]))
= ( h a s h ( o r z s t r [ i − 1 ] ) ∗ b a s e 2 i − 2 + h a s h ( n o t ( o r z s t r [ i − 1 ] ) ) ) − ( h a s h ( n o t ( o r z s t r [ i − 1 ] ) ) ∗ b a s e 2 i − 2 + h a s h ( o r z s t r [ i − 1 ] ) ) =(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[i1])base2i2+hash(not(orzstr[i1])))(hash(not(orzstr[i1]))base2i2+hash(orzstr[i1]))
= ( h a s h ( o r z s t r [ i − 1 ] ) − h a s h ( n o t ( o r z s t r [ i − 1 ] ) ) ) ∗ ( b a s e 2 i − 2 − 1 ) =(hash(orzstr[i-1])-hash(not(orzstr[i-1])))*(base^{2^{i-2}}-1) =(hash(orzstr[i1])hash(not(orzstr[i1])))(base2i21)
这让我们发现, h a s h ( o r z s t r [ i ] ) − h a s h ( n o t ( o r z s t r [ i ] ) ) hash(orzstr[i])-hash(not(orzstr[i])) hash(orzstr[i])hash(not(orzstr[i]))似乎是个神奇的东西。而我们的目的实际上是要找两个字符串 s t r A , s t r B strA,strB strA,strB使得
h a s h ( s t r A ) = h a s h ( s t r B ) ( m o d ( 2 64 ) ) hash(strA)=hash(strB)(mod(2^{64})) hash(strA)=hash(strB)(mod(264))
相当与
2 64 ∣ [ h a s h ( s t r A ) − h a s h ( s t r B ) ] 2^{64}|[hash(strA)-hash(strB)] 264[hash(strA)hash(strB)]
设数列 f [ i ] {f[i]} f[i] f [ i ] = h a s h ( o r z s t r [ i ] ) − h a s h ( n o t ( o r z s t r [ i ] ) ) f[i]=hash(orzstr[i])-hash(not(orzstr[i])) f[i]=hash(orzstr[i])hash(not(orzstr[i]))
这样就有:
f [ i ] = f [ i − 1 ] ∗ ( b a s e 2 i − 2 − 1 ) f[i]=f[i-1]*(base^{2^{i-2}}-1) f[i]=f[i1](base2i21)
还是有点不爽啊……我们再设数列 g [ i ] {g[i]} g[i] g [ i ] = b a s e 2 i − 1 − 1 g[i]=base^{2^{i-1}}-1 g[i]=base2i11
于是能写成:
f [ i ] = f [ i − 1 ] ∗ g [ i − 1 ] f[i]=f[i-1]*g[i-1] f[i]=f[i1]g[i1]
f [ i ] = f [ 1 ] ∗ g [ 1 ] ∗ g [ 2 ] ∗ . . . ∗ g [ i − 1 ] f[i]=f[1]*g[1]*g[2]*...*g[i-1] f[i]=f[1]g[1]g[2]...g[i1]
然后发现一个神奇的事情?
b a s e base base是奇数,则 b a s e base base的任意正整数次方也一定是奇数。所以对于任意的 i i i必有 g [ i ] g[i] g[i]为偶数,所以 2 i − 1 ∣ f [ i ] 2^{i-1}|f[i] 2i1f[i]
问题是不是结束了呢……发现没有……这样的话我们要使 2 64 ∣ f [ i ] 2^{64}|f[i] 264f[i],至少得让 i = 65 i=65 i=65……然后发现 ∣ o r z s t r [ 65 ] ∣ |orzstr[65]| orzstr[65]是个天文数字。
发现我们刚才那样分析太坑爹了……
i > 1 i>1 i>1时有:
g [ i ] = b a s e 2 i − 1 − 1 = ( b a s e 2 i − 2 − 1 ) ∗ ( b a s e 2 i − 2 + 1 ) = g [ i − 1 ] ∗ g[i]=base^{2^{i-1}}-1=(base^{2^{i-2}}-1)*(base^{2^{i-2}}+1)=g[i-1]* g[i]=base2i11=(base2i21)(base2i2+1)=g[i1]一个偶数
g [ 1 ] g[1] g[1]显然是偶数吧……
那么 4 ∣ g [ 2 ] 4|g[2] 4g[2] 8 ∣ g [ 3 ] . . . 8|g[3]... 8g[3]...
也就是说 2 i ∣ g [ i ] 2^i|g[i] 2ig[i]
所以 f [ i ] f[i] f[i]实际上有:
( 2 1 ) ∗ ( 2 2 ) ∗ ( 2 3 ) ∗ . . . ∗ ( 2 i − 1 ) ∣ f [ i ] (2^1)*(2^2)*(2^3)*...*(2^{i-1})|f[i] (21)(22)(23)...(2i1)f[i]
2 i ∗ ( i − 1 ) / 2 ∣ f [ i ] 2^{i*(i-1)/2}|f[i] 2i(i1)/2f[i]
i i i 12 12 12时,就有 66 66 66 2 2 2了哟!
这就是卡 b a s e base base为奇数时的方法。 o r z s t r [ 12 ] orzstr[12] orzstr[12] n o t ( o r z s t r [ 12 ] ) not(orzstr[12]) not(orzstr[12])即为所求。

而读入中 b a s e base base既有奇数又有偶数,直接在奇数构造的字符串后面加 64 64 64 a a a就可以了。

Code

#include<cstdio>
#include<cstring>
int i,now,j;
char s[1<<12];
int main(){
	puts("2113 1024");
	putchar(s[now=1]+97);
	for (i=0;i<11;i++,now<<=1)
		for (j=0;j<now;j++) putchar((s[now+j]=s[j]^1)+97);
	for (i=0;i<65;i++) putchar('a');
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值