密码(GCD有关)

来源:互联网 发布:axurerp7.0破解版mac 编辑:程序博客网 时间:2024/06/04 01:11

Problem

0N1当中有密码ai.

并且满足任意的1<=i,j,k<=n(ai+aj) % n=ak

已知有b[1..k1]k1个数都不是密码,以及一个数b[k]一定是密码,求|a|的最大值.

1<=k<=250000,k<=n<=1014

Solution

  • 如果有x是密码,那么Gcd(x,n)一定是密码.

    • 证明:因为xk % n一定是密码,xkny=Gcd(x,n),其中的k,y一定有解.
  • 所以t=Gcd(b[k],n)一定是密码.

  • t的因子全部求出来,如果一个因子能被b[1..k1]当中的任何一个数整除.

  • 那么这个因子都不合法,去除不合法的因子后,最小的因子w即为答案.

  • 这里有个技巧关于如何把因子能被b[1..k1]当中的数整除的去掉.

  • 我们可以先把b[1..k1]t的最大公因数给删了.

  • 然后再把最大公因数分解一下,其所有的因数也是不行的,或者可以直接暴力枚举一下.

  • a{}=w,2w,3w,kw,答案为n/w.

#include <cstdio>#include <iostream>#include <algorithm>#define fo(i,a,b) for (i = a; i <= b; i++)#define Maxn 300000using namespace std;int gcd(int a,int b) { return b?gcd(b,a%b):a; }int cnt,i,j,ans,n,k,f[Maxn],q[Maxn],a[Maxn];int main(){    scanf("%d%d",&n,&k);    fo(i,1,k) scanf("%d",&a[i]); a[k] = gcd(a[k],n);    fo(i,1,k-1) a[i] = gcd(a[i],a[k]);    for (i = 1; i * i <= a[k]; i++)        if (a[k] % i == 0) q[++cnt] = i, q[++cnt] = a[k] / i;    if (i*i==a[k]) cnt--;    sort(q+1,q+cnt+1);    fo(i,1,k-1)        f[lower_bound(q+1,q+cnt+1,a[i]) - q] = 1;    fo(i,1,cnt)      if (f[i])        fo(j,1,i-1)          if (q[i] % q[j] == 0) f[j] = 1;    for(ans = 1; f[ans]; ans++);    printf("%d\n",n/q[ans]);}

收获:

1.lower_bound函数用于查找q数组里第一个大于等于ai的数,相当于二分查找.

2.gcd的一条语句打法.

原创粉丝点击