• BZOJ2277: [Poi2011]Strongbox


    n<=10^14,0~n-1中有一些数是密码,且满足:a是密码,b是密码,那么(a+b)%n也是密码(a,b可相等),现小明试了m<=250000个数,前面都错,最后一个对,问n个数中最多有多少密码。

    好端端的一道数论题变卡常题。。

    根据那个规则,把最后猜到那个数字t带进去,那么t,2t,3t……都是密码,然而是%n下,所以0,(t,n),2*(t,n),……,n-(t,n)都是密码。

    那假如有别的数字是密码,那肯定也类似这样构成一个等间隔的东西。所以目标是找到这个最小的间隔。

    这个间隔应该能达到(t,n),也就是应该是(t,n)的因子,所以现在就可枚举(t,n)的因子检验一下其他不满足的位置会不会被搞到,也就是有没有x|Ai即可。

    然而因子个数*m爆炸了,于是花了一下午想有什么其他算法。。然而这是对的,只需要卡一卡即可

    因为10^14以内的数字最多只有17000多个因子,而对一个数Ai,其实检验(Ai,n)是否满足不被x整除也是一样的,因为Ai的其他因子在这个周期跳跃活动中没有啥用。于是把m个数都对n取gcd,然后去个重,复杂度就变成因子个数^2+mlogn了!

    哦。

     1 #include<cstring>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 //#include<assert.h>
     5 #include<algorithm>
     6 //#include<iostream>
     7 using namespace std;
     8 
     9 #define LL long long
    10 #define maxn 250011
    11 LL n; int m; LL a[maxn];
    12 LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
    13 bool check(LL x)
    14 {
    15     for (int i=1;i<=m;i++)
    16         if (a[i]%x==0) return 0;
    17     return 1;
    18 }
    19 int main()
    20 {
    21     scanf("%lld%d
    ",&n,&m);
    22     for (int i=1;i<=m;i++) scanf("%lld",&a[i]),a[i]=gcd(a[i],n);
    23     LL base=a[m]; sort(a+1,a+m); m=unique(a+1,a+m)-a-1;
    24     LL ans;
    25     for (int i=1;1ll*i*i<=base;i++) if (base%i==0)
    26     {
    27         if (check(i)) {ans=n/i; break;}
    28         else if (check(base/i)) {ans=n/(base/i);}
    29     }
    30     printf("%lld
    ",ans);
    31     return 0;
    32 }
    View Code
  • 相关阅读:
    http从发出请求到接收响应的旅行
    git(二)github的使用入门及搜索技巧
    git(一) 基础
    获取基于Internet Explorer_Server的聊天窗口内容
    主机字节与网络字节的转换
    SQL Server存储过程中防止线程重入处理方式
    利用NVelocity 模版生成文本文件
    C# async await 学习笔记2
    C# async await 学习笔记1
    imx6 工具链下载地址
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8158831.html
Copyright © 2020-2023  润新知