Hash Function

文章目录

  • 题意:
  • 题解:
  • 代码
    • NTT代码
    • FFT代码

题意:

给定n个互不相同的数,找一个最小的模域,使得它们在这个模域下互不相同。n<=5e5

题解:

考虑两个数a和b,a与b模m余数相同,当且仅当|a-b|能被m整除。
这样问题就转化成找到一个最下的m,使得m不是任意一个|ai-aj|约数(不会被m整除)
n<=5e5,所以直接暴力n2肯定不行
这时就要用到FFT/NTT加速
算N个数两两之差当然用FFT,利用多项式相乘即指数相加来做,(加减用指数,相乘用系数)
刚接触FFT的同学可能不明白,减法怎么用?FFT的模板不是乘法吗?
我们这样想:FFT可以快速求两个多项式的乘积,并求出每个指数所对应的系数,两个数相乘,指数相加,也就是如果我有一个多项式的指数为x,y(对应的系数都为1),另一个多项式的指数为z,w(对应的系数都为1),相乘后会得到指数为x+z,x+w,z+y,y+w,那如果我们将z和w分别为-x,-y,那就会得到x-x,x-y,y-x,y-y,这不正是x和y任意两数的差,该差是否存在就看他们的系数是否为1
这样就在N*logN求出所有差,(注意FFT中是没有指数为负的,所有我们加入一个偏移量MAX,让MAX-x,最后得到结果再加回去就行)
回到本题,要求是求最小的m,不是任意两数差的约数。现在我们求出所有的差并标记,然后枚举这个m,如果这个m的倍数均没有被标记,输出m
所以这算是个模板题了,会使用FFT/NTT板子

代码

NTT代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+100;
const int mx=5e5;
const int mod=998244353;
namespace IO{template<typename T>void write(T x){if(x<0){putchar('-');x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');}template<typename T> void read(T &x){x = 0;char ch = getchar();int f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+(ch-'0');ch=getchar();}x*=f;}
};
namespace Math{ll w;const int p=::mod;struct complex{ll real,imag;complex(ll a=0,ll b=0){real=a;imag=b;}friend complex operator*(const complex&a,const complex&b){complex ans;ans.real=((a.real*b.real%p+a.imag*b.imag%p*w%p)%p+p)%p;ans.imag=((a.real*b.imag%p+a.imag*b.real%p)%p+p)%p;return ans;}};ll x1,x2;ll ksm(ll a,ll b,ll p){ll ans=1;while(b){if(b&1) ans=(ans*a)%p;a=(a*a)%p;b>>=1;}return ans;}ll ksm(complex a,ll b,ll p){complex ans(1,0);while(b){if(b&1) ans=ans*a;a=a*a;b>>=1;}return ans.real%p;}bool Cipolla(ll n,ll&x0,ll&x1){n%=p;if(ksm(n,(p-1)>>1,p)==p-1) return false;ll a;while(true){a=rand()%p;w=((a*a%p-n)%p+p)%p;if(ksm(w,(p-1)>>1,p)==p-1) break;}complex x(a,1);x0=(ksm(x,(p+1)>>1,p)+p)%p;x1=(p-x0+p)%p;return true;}
};namespace NTT{#define mul(x,y) ((1ll*x*y>=mod?x*y%mod:1ll*x*y))#define dec(x,y) (1ll*x-y<0?1ll*x-y+mod:1ll*x-y)#define add(x,y) (1ll*x+y>=mod?1ll*x+y-mod:1ll*x+y)#define ck(x) (x>=mod?x-mod:x)typedef vector<int> Poly;int ksm(int a,int n,int mod=::mod){int res=1;while(n){if(n&1)res=1ll*res*a%mod;a=1ll*a*a%mod;n>>=1;}return res;}const int img=86583718;const int g=3,INV=ksm(g,mod-2);const int mx=21;int R[maxn<<2],deer[2][mx][maxn<<2],inv[maxn<<2];void init(const int t) {for(int p = 1; p <= t; ++ p) {int buf1 = ksm(g, (mod - 1) / (1 << p));int buf0 = ksm(INV, (mod - 1) / (1 << p));deer[0][p][0] = deer[1][p][0] = 1;for(int i = 1; i < (1 << p); ++ i) {deer[0][p][i] = 1ll * deer[0][p][i - 1] * buf0 % mod;deer[1][p][i] = 1ll * deer[1][p][i - 1] * buf1 % mod;}}inv[1] = 1;for(int i = 2; i <= (1 << t); ++ i)inv[i] = 1ll * inv[mod % i] * (mod - mod / i) % mod;}int NTT_init(int n) {int lim = 1, l = 0;while(lim < n) lim <<= 1, l ++ ;for(int i = 0; i < lim; ++ i)R[i] = (R[i >> 1] >> 1) | ((i & 1) << (l - 1));return lim;}void ntt(Poly &A, int type, int lim) {A.resize(lim);for(int i = 0; i < lim; ++ i)if(i < R[i])swap(A[i], A[R[i]]);for(int mid = 2, j = 1; mid <= lim; mid <<= 1, ++ j) {int len = mid >> 1;for(int pos = 0; pos < lim; pos += mid) {int *wn = deer[type][j];for(int i = pos; i < pos + len; ++ i, ++ wn) {int tmp = 1ll * (*wn) * A[i + len] % mod;A[i + len] = ck(A[i] - tmp + mod);A[i] = ck(A[i] + tmp);}}}if(type == 0) {for(int i = 0; i < lim; ++ i)A[i] = 1ll * A[i] * inv[lim] % mod;}}Poly poly_mul(Poly A, Poly B) {int deg = A.size() + B.size() - 1;int limit = NTT_init(deg);Poly C(limit);ntt(A, 1, limit);ntt(B, 1, limit);for(int i = 0; i < limit; ++ i)C[i] = 1ll * A[i] * B[i] % mod;ntt(C, 0, limit);C.resize(deg);return C;}Poly poly_inv(Poly &f, int deg) {if(deg == 1)return Poly(1, ksm(f[0], mod - 2));Poly A(f.begin(), f.begin() + deg);Poly B = poly_inv(f, (deg + 1) >> 1);int limit = NTT_init(deg << 1);ntt(A, 1, limit), ntt(B, 1, limit);for(int i = 0; i < limit; ++ i)A[i] = B[i] * (2 - 1ll * A[i] * B[i] % mod + mod) % mod;ntt(A, 0, limit);A.resize(deg);return A;}Poly poly_idev(Poly f) {int n = f.size();for(int i = n - 1; i-1>=0 ; -- i) f[i] = 1ll * f[i - 1] * inv[i] % mod;f[0] = 0;return f;}Poly poly_dev(Poly f) {int n = f.size();for(int i = 1; i < n; ++ i) f[i - 1] = 1ll * f[i] * i % mod;f.resize(n - 1);return f;}Poly poly_ln(Poly f, int deg) {Poly A = poly_idev(poly_mul(poly_dev(f), poly_inv(f, deg)));return A.resize(deg), A;}Poly poly_exp(Poly &f, int deg) {//cerr<<deg<<endl;if(deg == 1)return Poly(1, 1);Poly B = poly_exp(f, (deg + 1) >> 1);B.resize(deg);Poly lnB = poly_ln(B, deg);for(int i = 0; i < deg; ++ i)lnB[i] = ck(f[i] - lnB[i] + mod);int limit = NTT_init(deg << 1);ntt(B, 1, limit), ntt(lnB, 1, limit);for(int i = 0; i < limit; ++ i)B[i] = 1ll * B[i] * (1 + lnB[i]) % mod;ntt(B, 0, limit);B.resize(deg);return B;}Poly poly_pow(Poly&f,int k){f=poly_ln(f,f.size());for(auto&x:f)x=1ll*x*k%mod;return poly_exp(f,f.size());}Poly power(Poly f,int k1,int k2,int deg){int s=0;while(f[s]==0&&s<f.size())++s;if(1ll*s*k1>=deg){return vector<int>(deg);}int Inv=ksm(f[s],mod-2,mod);int Mul=ksm(f[s],k2);deg-=s;for(int i=0;i<deg;++i)f[i]=f[i+s];f.resize(deg);for(int i=0;i<deg;++i)f[i]=1ll*f[i]*Inv%mod;auto res1=poly_ln(f,deg);for(int i=0;i<res1.size();++i)res1[i]=1ll*res1[i]*k1%mod;auto res2=poly_exp(res1,deg);for(int i=0;i<deg;++i)res2[i]=1ll*res2[i]*Mul%mod;deg+=s;int now=s*k1;Poly res;res.resize(deg);for(int i=deg-1;i>=now;--i)res[i]=res2[i-now];for(int i=now-1;i>=0;--i)res[i]=0;return res;}Poly Poly_Sqrt(Poly&f,int deg){if(deg==1)return Poly(1,1);Poly A(f.begin(),f.begin()+deg);Poly B=Poly_Sqrt(f,(deg+1)>>1);Poly IB=poly_inv(B,deg);int lim=NTT_init(deg<<1);ntt(A,1,lim),ntt(IB,1,lim);for(int i=0;i<lim;++i){A[i]=1ll*A[i]*IB[i]%mod;}ntt(A,0,lim);for(int i=0;i<deg;++i){A[i]=(1ll*A[i]+B[i])%mod*inv[2]%mod;}A.resize(deg);return A;}Poly Sqrt(Poly&f,int deg){const int Pow=ksm(2,mod-2);int k1=1;if(f[0]!=1){k1=ksm(f[0],mod-2);for(int i=1;i<f.size();++i){f[i]=1ll*k1*f[i]%mod;}ll x0,x1;assert(Math::Cipolla(f[0],x0,x1));k1=min(x1,x0);f[0]=1;}auto Ln=poly_ln(f,deg);for(int i=0;i<f.size();++i){Ln[i]=1ll*Ln[i]*Pow%mod;}auto Exp=poly_exp(Ln,deg);for(int i=0;i<Exp.size();++i)Exp[i]=1ll*Exp[i]*k1%mod;return Exp;}Poly poly_sin(Poly&f,int deg){Poly A(f.begin(),f.begin()+deg);Poly B(deg),C(deg);for(int i=0;i<deg;++i){A[i]=1ll*A[i]*img%mod;}B=poly_exp(A,deg);C=poly_inv(B,deg);const int inv2i=ksm(img<<1,mod-2);for(int i=0;i<deg;++i){A[i]=1ll*(1ll*B[i]-C[i]+mod)%mod*inv2i%mod;}return A;}Poly poly_cos(Poly&f,int deg){Poly A(f.begin(),f.begin()+deg);Poly B(deg),C(deg);for(int i=0;i<deg;++i){A[i]=1ll*A[i]*img%mod;}B=poly_exp(A,deg);C=poly_inv(B,deg);const int inv2=ksm(2,mod-2);for(int i=0;i<deg;++i){A[i]=(1ll*B[i]+C[i])%mod*inv2%mod;}return A;}Poly poly_arcsin(Poly f,int deg){Poly A(f.size()),B(f.size()),C(f.size());A=poly_dev(f);B=poly_mul(f,f);for(int i=0;i<deg;++i){B[i]=dec(mod,B[i]);}B[0]=add(B[0],1);C=Poly_Sqrt(B,deg);C=poly_inv(C,deg);C=poly_mul(A,C);C=poly_idev(C);return C;}Poly poly_arctan(Poly f, int deg) {Poly A(f.size()), B(f.size()), C(f.size());A = poly_dev(f);B = poly_mul(f, f);B[0] = add(B[0], 1);C = poly_inv(B, deg);C = poly_mul(A, C);C = poly_idev(C);C.resize(deg);return C;}
};
using NTT::Poly;
using namespace IO;
int n,t;
Poly a,b;
bool vis[maxn];signed main(){//freopen("in.txt","r",stdin);//clock_t c1 = clock();NTT::init(NTT::mx-1);//for(auto x:tmp)cerr<<x<<" ";cerr<<endl;a.resize(maxn),b.resize(maxn);int n;read(n);if(n==1){cout<<1<<endl;return 0;}for(int i=0;i<n;++i){int x;read(x);a[x]=1;b[mx-x]=1;}auto res=NTT::poly_mul(a,b);for(int i=mx;i<=2*mx;++i){if(res[i]){vis[i-mx]=1;}}bool flag=0;for(int i=1;i<=mx+1;++i){int now=0;for(int j=i;j<=mx;j+=i){now|=(vis[j]!=0);if(now)break;}if(!now){cout<<i<<endl;flag=1;break;}}return 0;
}

FFT代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e6+50;
const double pi=acos(-1);
ll r[N],bits;
complex<double>A[N],B[N],w[N];
int dp[500005], vis[500005];
void FFT(complex<double> *P,ll op,ll N)
{for(ll i=1;i<N;i++){if(i>r[i])swap(P[i],P[r[i]]);}for(ll i=1;i<N;i<<=1){for(ll p=i<<1,j=0;j<N;j+=p){for(ll k=0;k<i;k++){complex<double>W=w[N/i*k];W.imag(W.imag()*op);complex<double> X=P[j+k],Y=W*P[j+k+i];P[j+k]=X+Y;P[j+k+i]=X-Y;}}}
}ll a[N],b[N],cnt[N];void solve(ll *a,ll *b,ll n,ll m)
{ll len;for(len=1,bits=0;len<=n+m;len<<=1)bits++;bits--;for(ll i=0;i<len;i++)A[i].real(0),A[i].imag(0),B[i].real(0),B[i].imag(0);for(ll i=0;i<=n;i++)A[i].real(a[i]);for(ll i=0;i<=m;i++)B[i].real(b[i]);for(ll i=0;i<len;i++)r[i]=(r[i>>1]>>1)|((i&1)<<bits);for(ll i=0;i<len;i++)w[i].real(cos(pi/len*i)),w[i].imag(sin(pi/len*i));FFT(A,1,len);FFT(B,1,len);for(ll i=0;i<len;i++)A[i]=A[i]*B[i];FFT(A,-1,len);for(ll i=0;i<=n+m;i++)a[i]=(ll)(A[i].real()/len+0.5);
}ll  hh[1500150];
ll cii=0;int main()
{ll n,m,k,x;scanf("%lld",&n);for(ll i=0;i<n;i++){scanf("%lld",&x);a[x]=1;b[500050-x]=1;}solve(a,b,500050,500050);//printf("a=%lld \n",a[1000]);for(ll i=0;i<=1000100;i++){if(a[i]!=0)hh[cii++]=abs(i-500050);}int Max=0;for(ll i=0;i<cii;i++){if(hh[i]>Max){Max=hh[i];}dp[hh[i]]=1;}int ans=Max+1;for(int i=Max;i>=n;i--){if(dp[i]==0){ans=i;continue;}if(vis[i]==1){continue;}for(int j=2;j*j<=i;j++){if(i%j==0){vis[j]=1;vis[i/j]=1;dp[j]=1;dp[i/j]=1;}}}printf("%d\n",ans);return 0;
}

Hash Function相关推荐

  1. 2021牛客多校1 - Hash Function(思维+FFT)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,现在要求找到一个 seedseedseed,使得所有数字变为 a[i]=a[i]modseeda[i]=a[i]\mod seeda[i] ...

  2. 2021牛客暑期多校训练营1 H Hash Function FFT\NTT

    传送门 文章目录 题意: 思路: 题意: 给你一个数组aaa,你需要找一个最小的模数xxx,使得aaa中每个数都模上xxx之后互不相同. n≤5e5,ai≤5e5,ai!=ajn\le5e5,a_i\ ...

  3. hash function/ hash table 背后的数学基础(二)

    hash function/ hash table 背后的数学基础 perfect hashing(完美哈希) 给定 nn 个键,构建一个静态表(static hash table,也即没有插入和删除 ...

  4. 取模运算与hash function

    取模运算常常对应于hash散列: k%m k\;\%\;m 如果从映射(map)的角度看待取模运算的话,其实是对原始空间取值范围的一种放缩,比如缩放到 [0,m−1][0,m-1](整数). 如果这时 ...

  5. hash function/ hash table 背后的数学基础

    原文请见:Load Balancing and the Power of Hashing 如果你参加一次软件工程师的面试并你被问到一个很难的有关算法的题目,那么你最好考虑使用散列函数(hash tab ...

  6. H Hash Function

    Hash Function 题目描述 For a given set S={a0,a1,a2,...,an−1}S = \{a_0, a_1, a_2, ..., a_{n-1}\}S={a0​,a1 ...

  7. C++ STL源码分析——一个万用的 hash function

    [侯捷-SL体系结构内核分析-一个万用的 hash function] 我们知道,unordered_set / unordered_multiset / unordered_map / unorde ...

  8. Hash Function 2021牛客暑期多校训练营1 数论 + NTT

    Hash Function solution 任意选择该集合中的两个数,a,b,由于a%mod<>b%mod任意选择该集合中的两个数,a,b,由于a\%mod<>b\%mod任 ...

  9. POSEIDON: A New Hash Function for Zero-Knowledge Proof Systems 学习笔记

    1. 引言 Grassi等人2019年论文<POSEIDON: A New Hash Function for Zero-Knowledge Proof Systems>. 前序博客有: ...

最新文章

  1. setcookie无效
  2. spring-boot启动源码学习-1
  3. centos安装python3小白_Centos7 安装Python3
  4. 串口屏与6050_MPU6050温度值的读取与转换及串口通信,请指导
  5. Event/window.Event属性和方法
  6. 状态模式 设计模式_设计模式:状态
  7. 无线模块的电源设计指南
  8. 江苏省计算机分级考试试题,江苏省计算机等级考试基础知识考题.doc
  9. Python 关键词触发的魔法方法
  10. 洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)
  11. stm32f103c8t6开发版点亮oled屏幕工程文件_OLED液晶屏如何显示中文呢
  12. 工业机器人技术基础及其应用总结
  13. 商务数据分析与应用学习笔记
  14. 实现基于SSM开发房屋租赁系统
  15. S变换介绍(附代码)
  16. 语音数据增强—使用kaldi对语音加噪
  17. 高频故障-office背景有水印的解决方案
  18. 论文笔记:多标签学习——LIFT算法
  19. 第14届军警狙击手世界杯:中国队包揽全部冠军
  20. 改善睡眠的小妙招,这些双十一推荐助眠好物你要知道

热门文章

  1. 中国最险六大寺庙,最后一座至今无人登临
  2. 35岁老程序员因身体原因没加班,老板:不想干就滚蛋
  3. 掌握神经网络模型的快捷方式
  4. 有效处理 Java 异常三原则
  5. Oracle常用知识总结
  6. bitmap 转byte[]后读取_闲谈redis的bitmap
  7. 小猿学python_小猿圈python入门之转行零基础该如何学Python?
  8. react dispatch_React测试的那些事(三) React Hook 测试实例
  9. 大厂Java初级开发工程师!!!面试必问项之Set实现类:TreeSet
  10. c语言求平衡因子,平衡二叉树(AVL树)的基本操作