• CDOJ 1314 Hash Perfectly FFT


    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 ightarrow 6) in index (2). Insert (10) next, there would be a linked list (2 ightarrow 6 ightarrow 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., (1leq array\_sizeleq 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.

    (1leq n, limit, keyleq 2*10^5)

    Output

    Print the smallest (array\_size) which can minimize (ASL).

    Sample Input

    4 4
    1 2 6 10

    Sample Output

    3

    Hint

    题意

    现在你有n个数,然后哈希是指b[i]=a[i]%k

    现在让你找到一个合适的k,使得冲突的对数最少,这个k需满足0<=k<=limit

    题解:

    若一个位置冲突了k次,则对n*ASL的贡献是k*(k+1)/2,相当于k个数两两冲突的对数加k。
    对于两个数a,b,他们只会在(a-b) % array_size == 0时冲突。
    利用FFT,可把所有a-b的可能取值对应的个数算出来。对于每个array_size,算出a-b=array_size, a-b=2array_size, a-b=3array_size, …的个数,就可以直接得到ASL的值。
    复杂度O(nlogn)

    代码

    #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)
    {
    	rader(F,len);
    	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;
    }
  • 相关阅读:
    关于JSONP
    使用stylelint对CSS/Sass做代码审查
    关于input的file框onchange事件触发一次失效的新的解决方法
    HTML5 之 FileReader(图片上传)
    document.domain
    window.hostory(浏览器的历史记录)
    事件DOMContentLoaded和load的区别
    JavaScript中---作用域
    关于repaint(重绘)和reflow( 回流)
    bootstrap兼容性问题
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5380044.html
Copyright © 2020-2023  润新知