题解 | #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;
}
全部评论

相关推荐

最终还是婉拒了小红书的offer,厚着脸皮回了字节。其实这次字节不管是组内的氛围、HR的沟通体验,都比之前好太多,开的薪资也还算过得去,这些都是让我下定决心的原因之一。但最核心的,还是抵不住对Agent的兴趣,选择了Ai&nbsp;Coding这么一个方向。因为很多大佬讲过,在未来比较火的还是属于那些更加垂类的Agent,而Ai&nbsp;Coding恰好是Coding&nbsp;Agent这么一个领域,本质上还是程序员群体和泛程序员群体这个圈子的。目前也已经在提前实习,也是全栈这么一个岗位。就像最近阿里P10针对前端后端等等不再那么区分,确实在Agent方向不太区分这个。尤其是我们自己做AI&nbsp;Coding的内容,基本上90%左右的内容都是AI生成的,AI代码仓库贡献率也是我们的指标之一。有人说他不好用,那肯定是用的姿态不太对。基本上用对Skill、Rules&nbsp;加上比较好的大模型基本都能Cover你的大部分需求,更别说Claude、Cursor这种目前看来Top水准的Coding工具了(叠甲:起码在我看来是这样)。所以不太区分的主要原因,还是针对一些例如Claude&nbsp;Code、Cursor、Trae、Codex、CC等一大堆,他们有很多新的概念和架构提出,我们往往需要快速验证(MVP版本)来看效果。而全栈就是这么快速验证的一个手段,加上Ai&nbsp;Coding的辅助,目前看起来问题不大(仅仅针对Agent而言)。而且Coding的产品形态往往是一个Plugin、Cli之类的,本质还是属于大前端领域。不过针对业务后端来看,区分还是有必要的。大家很多人也说Agent不就是Prompt提示词工程么?是的没错,本质上还是提示词。不过现在也衍生出一个新的Context&nbsp;Eneering,抽象成一种架构思想(类比框架、或者你们业务架构,参考商品有商品发布架构来提效)。本质还是提示词,但是就是能否最大化利用整个上下文窗口来提升效果,这个还是有很多探索空间和玩法的,例如Cursor的思想:上下文万物皆文件,&nbsp;CoWork之类的。后续也有一些Ralph&nbsp;Loop啥的,还有Coding里面的Coding&nbsp;Act姿态。这种才是比较核心的点,而不是你让AI生成的那提示词,然后调用了一下大模型那么简单;也不是dify、LangGraph搭建了一套workflow,从一个node走到另外一个node那么简单。Agent和WorkFLow还是两回事,大部分人也没能很好的区分这一点。不过很多人说AI泡沫啥啥啥的,我们ld也常把这句话挂在嘴边:“说AI泡沫还是太大了”诸如此类。我觉得在AI的时代,懂一点还是会好一点,所以润去字节了。目前的实习生活呢,除了修一些Tools的问题,还包括对比Claude、Cursor、Trae在某些源码实现思想上的点,看看能不能迁移过来,感觉还是比较有意思。不过目前组内还是主要Follow比较多,希望下一个阶段就做一些更有创新的事情哈哈。这就是一个牛马大学生的最终牧场,希望能好好的吧。说不定下次发的时候,正式AI泡沫结束,然后我又回归传统后端这么一个结局了。欢迎交流👏,有不对的🙅不要骂博主(浅薄的认知),可以私聊交流
聪明的芭乐等一个of...:佬可以推荐一些和aicoding相关的学习资料吗?最近特别想学习这个方向
点赞 评论 收藏
分享
评论
45
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务