BZOJ 3097(Hash Killer I-哈希%u64的不可行)

3097: Hash Killer I

Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 76  Solved: 34
[Submit][Status][Discuss]

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

这题要一定的数论知识(其实不要……)

如果s[1]=1 s[i]=s[i-1]+s[i-1].flip(1...size)

则有

strlen(s[i])=2^(i-1)

若设f[i]=hash(s[i])-(hash(!s[i]))=2^k * t (t是奇数)

则易证(把hash值有base带,慢慢算……)

f[i]=f[i-1]*(base^[2^(i-2)]-1)

∵2^i-1=(2^(i-1)-1)*(2^(i-1)+1),

所以k很大。  

如果base是偶数,那么只要最高位不同,其它都相同让其溢出就行。


#include<cstdio>
#include<iostream>
#include<functional>
#include<bitset>
#include<string>
using namespace std;
#define MAXN (100000+10)
int n,l;
bitset<MAXN> s;
int main()
{
	n=MAXN-10;
	int bin=1;
	s[1]=1;
	for (int i=2;i<=13;i++,bin<<=1)
	{
		for(int j=bin+1;j<=bin*2;j++)
			s[j]=s[j-bin]^1;
	}
	cout<<n<<' '<<bin/2<<endl;
	for (int i=1;i<=bin;i++)
	{
		if (s[i]) cout<<'a';
		else cout<<'b';
	}
	cout<<'b';
	for (int i=bin+2;i<=n;i++) cout<<'a';

	cout<<endl;
	return 0;
}

Project Euler 47-Distinct primes factors

Distinct primes factors

Problem 47

The first two consecutive numbers to have two distinct prime factors are:

14 = 2 × 7
15 = 3 × 5

The first three consecutive numbers to have three distinct prime factors are:

644 = 2² × 7 × 23
645 = 3 × 5 × 43
646 = 2 × 17 × 19.

Find the first four consecutive integers to have four distinct prime factors. What is the first of these numbers?

 

Answer:
134043
Completed on Sat, 6 Apr 2013, 05:40

Go to the thread for problem 47 in the forum.

 

n=1000000
a=[0 for i in range(n+1)]
i=2
while i< =n: if (a[i]==0): j=2*i while j

PE 47(Distinct primes factors-Python数组)

Distinct primes factors

Problem 47

The first two consecutive numbers to have two distinct prime factors are:

14 = 2 × 7
15 = 3 × 5

The first three consecutive numbers to have three distinct prime factors are:

644 = 2² × 7 × 23
645 = 3 × 5 × 43
646 = 2 × 17 × 19.

Find the first four consecutive integers to have four distinct prime factors. What is the first of these numbers?

Answer:
134043
Completed on Sat, 6 Apr 2013, 05:40

Go to the thread for problem 47 in the forum.

本题考察Python中数组的运用:
n=1000000
a=[0 for i in range(n+1)]
i=2
while i<=n:
    if (a[i]==0):
        j=2*i
        while j<n:
            a[j]=a[j]+1
            j+=i
    i+=1
for i in range(1,n+1-3):
    if (a[i]==4 and a[i+1]==4 and a[i+2]==4 and a[i+3]==4):
        print i

Project Euler 48-Self powers

Self powers

Problem 48

The series, 11 + 22 + 33 + ... + 1010 = 10405071317.

Find the last ten digits of the series, 11 + 22 + 33 + ... + 10001000.

 

Answer:
9110846700
Completed on Fri, 5 Apr 2013, 12:33

Go to the thread for problem 48 in the forum.

 

ans=0
i=1
F=10**10
for i in range(1,1001):
p=1
for j in range(i): p=p*i%F
ans=(ans+p)%F
print i
print ans

Project Euler 3-Largest prime factor

Largest prime factor

Problem 3

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

 

Answer:
6857
Completed on Fri, 5 Apr 2013, 12:14

Go to the thread for problem 3 in the forum.

 

import math
n=600851475143
i=2
print math.sqrt(n)
while i< =math.sqrt(n): if (n%i==0): while (n%i==0): n=n/i print i; i=i+1 print n

Project Euler 2-Even Fibonacci numbers

Even Fibonacci numbers

Problem 2

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

Answer:
4613732
Completed on Fri, 5 Apr 2013, 06:37

Go to the thread for problem 2 in the forum.

 Even(是偶数的意思……(─.─|||

f=[1,1,1]
i=2
ans=0
while f[i]+f[i-1]<4000000:
i=i+1
f.append(f[i-1]+f[i-2])
if (f[i]%2==0): ans=ans+f[i]
print sum(f)-1,f,ans

UVA 11538(Chess Queen-矩阵对角线长度)

Problem A
Chess Queen
Input:
Standard Input

Output: Standard Output

 

王后互相攻击的前提是在一行,一列,或一对角线。:

 

在 (NxM) 的棋盘上 2 王后互相攻击,求方案数.

 

Input

 

输入数据不超过 5000 行 ,每行为M and N (0< M, N£106) ,数据以0 0结尾.

 

Output

 

每行一个整数表示方案数,保证它在u64范围内.

 

Sample Input                              Output for Sample Input

2 2

100 223

2300 1000

0 0

12

10907100

11514134000                                                                        

 

Problemsetter: Shahriar Manzoor

Special Thanks to: Mohammad Mahmudur Rahman

首先,一个矩形的长宽若为m,n(m>=n)

那么它一个方向的对角线应为1..(n-1)各2条,n有(m-n+1)条

知道这个的化,本题就转化为,在一列一行或一对角线任取2点,有几种取法。

#include<cstdio>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
#define MAXN (1000000+10)
unsigned long long n,m;
int main()
{
	while (cin>>n>>m&&n&&m)
	{
		if (n>m) swap(n,m);
		cout<<n*m*(n+m-2)+2*n*(n-1)*(3*m-n-1)/3<<endl;
	}
	return 0;
}



BZOJ 3098(Hash Killer II-生日攻击)

3098: Hash Killer II

Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 66  Solved: 22
[Submit][Status][Discuss]

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') % Mod;
u64是无符号int64,范围是[0, 2^64)。
base是一个常量,VFleaKing会根据心情决定其值。
Mod等于1000000007。
VFleaKing还求出来了base ^ l % Mod,即base的l次方除以Mod的余数,这样就能方便地求出所有长度为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)
{
 const int Mod = 1000000007;

 u64 hash_pow_l = 1;
 for (int i = 1; i <= l; i++)
  hash_pow_l = (hash_pow_l * base) % Mod;

 int li_n = 0;
 static int li[MaxN];

 u64 val = 0;
 for (int i = 0; i < l; i++)
  val = (val * base + s[i] - 'a') % Mod;
 li[li_n++] = val;
 for (int i = l; i < n; i++)
 {
  val = (val * base + s[i] - 'a') % Mod;
  val = (val + Mod - ((s[i - l] - 'a') * hash_pow_l) % Mod) % Mod;
  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

如果一个房间里有23个或23个以上的人,那么至少有两个人的生日相同的概率要大于50%。

Source

生日攻击:如果你在n个数中随机选数,那么最多选√n次就能选到相同的数(不考虑Rp broken)

同样的,这题的Hash值在0到1000000007.

那就要选差不多10^5次

唯一注意的是l要取大,使得方案数超过Mod

否则就不可能有2个数有相同的Hash值

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXN (100000)
int n=MAXN,l=13;
int main()
{
	cout<<n<<' '<<l<<endl;
	for(int i=1;i<=n;i++) cout<<char(rand()%26+'a');
	cout<<endl;
	return 0;
}