题解 | #Hash Function#

Hash Function

https://ac.nowcoder.com/acm/contest/11166/H

个数两个相减(相加)先序知识

Describe

给定 个数 :
的集合

注意: 指的是 中的每一个元素与 中的每一个元素相加,即

相关题型:Hash Function B-小圆前辈的素数

Solve

朴素双重循环复杂度为 ,对于数据量大于 的问题显然无法解决。

考虑 我们将上述集合换一种表达式:
则对于 ,转化为

因此,我们只要将一个多项式中的 的系数赋值为 ,其他赋值为 。进行一遍FFT后,检验 的系数,若 的系数大于等于 ,则

提示:对于减法,实际上是加上一个负数,因为负下标的问题,可以先统一加上一个偏移量,最后减去即可得到原值。

具体问题讲解
题面描述 [Hash Function]

给定一个集合
考虑 ,求最小的整数 ,使得 无冲突,即若 ,则

Slove

我们需要考虑的是 ,都存在 .

上述结论很容易证明:

考虑: ,则
显然
如果 ,则 。则 不合法。

也就是说 的因子全都不满足条件,同时对于其他数,一定都是满足条件的,证明如下:

因为 ;且 ;则
说明 ,同时对于每一对 都成立,故该 合法。

综上所述:我们需要快速求出所有的 ,并求出 的所有因子。

即我们需要求出
上述做法即可在 内完成,根据经验,中元素不超过个,同时元素不超过 ,用正向筛选法可以在内筛选出所有因子。

代码:

#include <cstdio>
#include <complex>
#include <cmath>
using namespace std;

int n,m;
typedef complex<double> CP;
const int lim = 1<<21;
const double Pi = acos(-1);
const int P = 500001;
CP a[lim],b[lim];
bool vis[lim];

void FFT(CP *x,int lim,int inv) // 板子而已
{
   int bit = 1,m;
   CP stand,now,temp;
   while((1<<bit) < lim) ++bit;
   for (int i = 0; i < lim; ++i)
   {
       m = 0;
       for (int j = 0; j < bit; ++j)
           if(i & (1<<j)) m |= (1<<(bit-j-1));
       if(i < m) swap(x[m],x[i]);
   }
   for (int len = 2; len <= lim; len <<= 1)
   {
       m = len >> 1;
       stand = CP(cos(2*Pi/len),inv*sin(2*Pi/len));
       for (CP *p = x; p != x+lim; p += len)
       {
           now = CP(1,0);
           for (int i = 0; i < m; ++i,now*=stand)
           {
               temp = now * p[i+m];
               p[i+m] = p[i] - temp;
               p[i] = p[i] + temp;
           }
       }
   }
   if(inv == -1) 
       for (int i = 0; i < lim; ++i)
           x[i].real(x[i].real()/lim);
}

bool check(int x)
{
   for (int i = x; i <= P; i += x)
   {
       if (vis[i] == 1) return 0;
   }
   return 1;
}

int main()
{
   int x;
   scanf("%d",&n);
   for (int i = 0; i < n; ++i)
   {
       scanf("%d",&x);
       a[x].real(1);
       b[P - x].real(1); // 负数做偏移
   }
   int num = 1 << 20;
   FFT(a,num,1);
   FFT(b,num,1);
   for (int i = 0; i < num; ++i)
       a[i] *= b[i];
   FFT(a,num,-1);
   for (int i = 0; i <= num; ++i)
   {
       x = (int)floor(a[i].real()+0.5);
       if (x > 0) vis[abs(i - P)] = 1;
   }
   for (int  i = n; i < P+1; ++i)
       if (check(i))
       {
           printf ("%d\n",i);
           break;
       }
   return 0;
}
全部评论

相关推荐

#我和xx公司的爱恨情仇#&nbsp;怎么会有这么**的公司!实习ld跟我说,在这实习秋招会有很大优势,没太大问题;线下一面二面水的很,手撕都是easy,二面面试官甚至说,你随便手撕个题目就行,找个代码量多的题目,然后我写了一个bfs图算法。主管面也是基本上纯聊天,然后甚至问我预期薪资,我说虽然我有互联网公司offer但是更想来华子,认可企业文化。面试完后,保温电话说根据面评开14a没问题,过了一段时间后去问了对接人,先说11月底开,后来说12月底开,昨天去问,他说你不是签了美团了吗,我们已经发完全部offer了。tmd那你不早说,我还在这等。我问了我们这个部门的其他实习生(三级部门下8个实习生,我们四级部门下就有5个,按理说我们部门应该缺人吧),结果其他实习生全军覆没,之前都收到降温电话要签个其他offer保底,实习生中甚至有人空白三方在allin华子,最逆天的是,其中一个是优秀实习生,他也没开出来。问那个优秀实习生,他说他在这实习时接口人天天给他洗脑说,在这实习只有不想来的,没有泡不出来的(如图1)。我接口人也是这么跟我说的,说我们2012实验室下面都偏预研,部门加班少,我们部门确实还行,而且本身华为比互联网稳定,后期还有股票,退休保留股票一直分红(补充:只有5%的人可以熬到40岁以上退休分股),你看看华为那么多od,人家为什么社招想来华为当od呢,因为华为真的稳定啊(后来想想他们来当od应该是没有更好的选择了吧,xhs上那个清华姚班都来华为当od)。我跟几个实习生已经转投其他部门了,那个优秀实习生去找别的部门hr时,人家问:你优秀实习生也要换部门吗,没遇到你这种情况之前为了选华为还是美团我还纠结了1个多月,现在想想真**,这**公司谁来谁知道,华子稳定个**,这里补充一下,35岁下岗就是华子最早提出来的。还有华为内部转岗的事,后来问了下很多大公司都可以内转,华子内转还要背绩效,去新部门会有很大绩效压力,原部门绩效太差还不能转,****。这**泡池子机制也是遥遥领先,其他互联网公司纷纷效仿。还有那5%公积金真恶心。之前认识一个腾讯提前批哥们,他杭电本科生,hr打电话还恶心他,给他开13a,总包比腾讯少20w,跟他说一大堆什么企业稳定,前景好,技术遥遥领先(图2)另外,还有个签约阿里被华为恶心的(图3)我和腾讯提前批的哥们的故事是真的,可以保证确有其事,图3是道听途说,不保证真实性,但我觉得这**公司真有可能发生这种诈骗故事
好吃的麦乐鸡块:这公司真的恶心,毫无信誉可言
点赞 评论 收藏
分享
评论
45
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务