2021牛客暑期多校 1H - Hash Function (多项式乘法FFT、类埃氏筛)
题意
给定\(n\)个互不相同的范围在\([0,500000]\)内的数
要求求出最小的模数\(seed\),使得所有数与\(seed\)取模后仍是互不相同的
思路(快速傅里叶变换)
大部分队伍都是直接当想法题过掉的,本篇给出使用多项式乘法的解法
首先,答案的最小值应是数字的数量\(n\),最大值应是数字的最大值\(+1\)
所以得出\(seed\in[n,500001]\)(根据输入可以再缩小,但没必要)
然后考虑本题要求
假如我们当前选择了一个\(seed\),使得某两个数\(a,b\)对其取模后相同,即
换言之,实际上\(a\)与\(b\)的差值也就是\(seed\)的倍数,即
所以对于\(seed\)的选取,一定不能是任意两个数的差值(或者这个差值的因子)
所以需要处理出这些数字两两之间的差值,这里可以借助多项式乘法将\(O(n^2)\)的枚举优化成\(O(nlogn)\)
由于计算的是\(a-b\),并且(根据\(FFT\)板子易知)在多项式乘法中不允许出现负数下标(因为多项式乘法原本计算的是两两之和的种类数\(a+b\),而不是本题中两两之差)
为了能让\(a\)和\(-b\)能够分别存储,所以我们需要为每个数加上一个基础值\(avg\),使得\(a+avg\)和\(-b+avg\)都在\(0\)以上
显然,\(avg\ge 500000\)
然后跑一遍\(FFT\),求出所有\((a+avg)+(-b+avg)\)的种类数
将得到的多项式提取出来,\((a+avg)+(-b+avg)-avg\times 2\)也就是\(a-b\)的值,将每种差值是否出现记录在\(vis\)数组中
接下来就是最后一步,将所有出现的差值及其因子直接排除,选出最小的答案
枚举因子可能需要\(O(n\sqrt{n})\),可能会炸
所以我们直接枚举\(seed\in[n,500001]\),对于某个可能是答案的数(不是差值),找一下是否存在差值是其倍数(直接枚举倍数即可),如果没有差值是其倍数,则找到了答案
#include<bits/stdc++.h>
using namespace std;
const int N=3000050;
const double PI=acos(-1.0);
const int avg=500000;
int vis[500050];
int lim=1,rev[N];
struct cp
{
double x,y;
cp(double u=0,double v=0){x=u,y=v;}
friend cp operator +(const cp &u,const cp &v){return cp(u.x+v.x,u.y+v.y);}
friend cp operator -(const cp &u,const cp &v){return cp(u.x-v.x,u.y-v.y);}
friend cp operator *(const cp &u,const cp &v){return cp(u.x*v.x-u.y*v.y,u.x*v.y+u.y*v.x);}
}f[N],g[N];
void FFT(cp *a,int tp)
{
for(int i=0;i<lim;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int md=1;md<lim;md<<=1)
{
cp rt=cp(cos(PI/md),tp*sin(PI/md));
for(int stp=md<<1,pos=0;pos<lim;pos+=stp)
{
cp w=cp(1,0);
for(int i=0;i<md;i++,w=w*rt)
{
cp x=a[pos+i],y=w*a[pos+md+i];
a[pos+i]=x+y;
a[pos+md+i]=x-y;
}
}
}
}
void initFFT(int n)
{
int lg=0;
while(lim<=n)
lg++,lim<<=1;
for(int i=0;i<lim;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int d;
scanf("%d",&d);
//记录d和-d
f[avg+d].x+=1;
g[avg-d].x+=1;
}
//根据乘法的值域预处理FFT蝴蝶变换,加快FFT速度
initFFT(avg*4);
//正常FFT流程
FFT(f,1),FFT(g,1);
for(int i=0;i<lim;i++)
f[i]=f[i]*g[i];
FFT(f,-1);
//记录是否存在差值为i的情况(i+avg*2即多项式乘法内的结果下标)
for(int i=1;i<=500001;i++)
vis[i]=(int)round(f[i+avg*2].x/lim);
//枚举seed,判断可行性
for(int i=n;i<=500001;i++)
{
if(vis[i]>0)
continue;
for(int j=i+i;j<=500000;j+=i)
{
//如果存在差值j(i的倍数),则i不可行
if(vis[j])
{
vis[i]=1;
break;
}
}
//i可行,作为模数输出即可
if(vis[i]==0)
{
cout<<i<<'\n';
return 0;
}
}
return 0;
}
原文地址:https://www.cnblogs.com/stelayuri/p/15024453.html
- JDK8 stream toMap() java.lang.IllegalStateException: Duplicate key异常解决(key重复)
- 如约而至,Java 10 正式发布!
- Intellij IDEA查看所有断点
- Spring Boot国际化支持
- 有记忆会推理的可微分神经计算机,DeepMind现在开源了代码
- Spring Boot整合Thymeleaf模板引擎
- Spring Boot实现热部署
- Java中的宏变量,宏替换详解。
- 类、变量、块、构造器、继承初始化顺序,终极解答。
- Spring Boot Debug调试
- Maven精选系列--classifier元素妙用
- PostgreSQL里面的一些命令小结
- Java中创建String的两道面试题及详解
- PostgreSQL主备环境搭建
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- BFE.dev前端刷题#58. 获取DOM tree高度
- 如何在Tungsten Fabric上整合裸金属服务器(附配置验证过程)
- 逐行阅读Spring5.X源码(三) BeanDefinition的实现类详解,拔高
- 逐行阅读Spring5.X源码(番外篇)BeanDefinition到底有多重要
- 逐行阅读Spring5.X源码(番外篇)AnnotatedBeanDefinitionReader的作用
- 逐行阅读Spring5.X源码(四) BeanFactory——核心容器bean工厂
- 逐行阅读Spring5.X源码(五) 初探BeanFactoryPostProcessor后置处理器,难,特别难。
- 逐行阅读Spring5.X源码(六) ClassPathBeanDefinitionScanner扫描器
- 逐行阅读Spring5.X源码(番外篇)自定义扫描器, Mybatis是如何利用spring完成Mapper扫描的
- 逐行阅读Spring5.X源码(七)扫描和注册神器 ConfigurationClassPostProcessor ,学此类者,胜过学九阳神功!胆小勿入!
- 「Mysql索引原理(三)」Mysql中的Hash索引原理
- RNN、lstm、gru详解
- 「Mysql索引原理(四)」单列索引
- 「Mysql索引原理(五)」多列索引
- 「Mysql索引原理(六)」聚簇索引