qscqesze
Published on 2017-09-02 11:31 in 暂未分类 with qscqesze

# Hash Perfectly

## 题目连接：

http://acm.uestc.edu.cn/#/problem/show/1314

## Description

In computing, a hash table is a data structure used to implement an associative array, a structure that can map keys to values.

A hash table uses a hash function to compute an index into an array of buckets or slots, from which the desired value can be found. A common hash function is $index=key\ \%\ array\\_size$ ($\%$ is modulo operator), but it may cause some collisions.

For example, if keys are $1,2,6,10$, and we choose $array\\_size=4$, the indexes will be $1,2,2,2$, where some collisions happen.

To solve the collision, we can use the method known as separate chaining with linked lists.

Seeing the example again, when we try to insert $6$, because its index $2$ is used, we build a linked list in index $2$, and there would be $2\rightarrow 6$ in index $2$. Insert $10$ next, there would be a linked list $2\rightarrow 6\rightarrow 10$ in index 2.

To calculate the efficiency of the hash function, we define a value called $ASL$ (Average search length):
$ASL=\frac{1}{n}\sum_{i=1}^{n}c_i$
$c_i$ is the number of times to compare when we search the $i^{th}$ key.

Using the example above again, $c_1=1,c_2=1,c_3=2,c_4=3$, so $ASL=\frac{1}{4}(1+1+2+3)=1.75$.

It's obvious that $ASL$ can minimize when we choose a sufficiently large $array\\_size$, but in fact due to the limitation of memory, $array\\_size$ must be no more than $limit$, i.e., $1\leq array\\_size\leq limit$.

Now you are given n keys, try to choose a proper $array\\_size$ to minimize $ASL$. If there are multiple answers, choose the smallest one.

## Input

The first line contains two integers $n$ and $limit$.

The second line contains $n$ integers, where $i^{th}$ integer indicates the $i^{th}$ key.

$1\leq n, limit, key\leq 2*10^5$

## Output

Print the smallest $array\\_size$ which can minimize $ASL$.

4 4
1 2 6 10

3

## 代码

#include<bits/stdc++.h>

using namespace std;

const int N = 600040;
const double pi = acos(-1.0);

int len=1<<19;

struct Complex
{
double r,i;
Complex(double r=0,double i=0):r(r),i(i) {};
Complex operator+(const Complex &rhs)
{
return Complex(r + rhs.r,i + rhs.i);
}
Complex operator-(const Complex &rhs)
{
return Complex(r - rhs.r,i - rhs.i);
}
Complex operator*(const Complex &rhs)
{
return Complex(r*rhs.r - i*rhs.i,i*rhs.r + r*rhs.i);
}
} va[N],vb[N];

void rader(Complex F[],int len) //len = 2^M,reverse F[i] with  F[j] j为i二进制反转
{
int j = len >> 1;
for(int i = 1;i < len - 1;++i)
{
if(i < j) swap(F[i],F[j]);  // reverse
int k = len>>1;
while(j>=k)
{
j -= k;
k >>= 1;
}
if(j < k) j += k;
}
}

void FFT(Complex F[],int len,int t)
{
for(int h=2;h<=len;h<<=1)
{
Complex wn(cos(-t*2*pi/h),sin(-t*2*pi/h));
for(int j=0;j<len;j+=h)
{
Complex E(1,0); //旋转因子
for(int k=j;k<j+h/2;++k)
{
Complex u = F[k];
Complex v = E*F[k+h/2];
F[k] = u+v;
F[k+h/2] = u-v;
E=E*wn;
}
}
}
if(t==-1)   //IDFT
for(int i=0;i<len;++i)
F[i].r/=len;
}

void Conv(Complex a[],Complex b[],int len) //求卷积
{
FFT(a,len,1);
FFT(b,len,1);
for(int i=0;i<len;++i) a[i] = a[i]*b[i];
FFT(a,len,-1);
}
int n,limit;
int a[N];
long long num[N],sum[N];
void solve()
{
scanf("%d%d",&n,&limit);
int Mx = 0;
for(int i=0;i<n;i++)
{
int x;scanf("%d",&a[i]);
va[a[i]].r+=1;
vb[200000-a[i]].r+=1;
}
Conv(va,vb,len);
for(int i=0;i<=200000;i++)
num[i]=(long long)(va[200000+i].r+0.5);
long long ans1=1e18,ans2=0;
for(int i=1;i<=limit;i++)
{
long long cnt = 0;
for(int j=i;j<=len;j+=i)
cnt+=num[j];
if(cnt<ans1)
{
ans1=cnt;
ans2=i;
}
}
cout<<ans2<<endl;
}
int main()
{
solve();
return 0;
}
posted @ 2016-04-11 20:32  qscqesze  阅读(...)  评论(...编辑  收藏