zoukankan      html  css  js  c++  java
  • bzoj 2277 [Poi2011]Strongbox 数论

    2277: [Poi2011]Strongbox

    Time Limit: 60 Sec  Memory Limit: 32 MB
    Submit: 527  Solved: 231
    [Submit][Status][Discuss]

    Description

    Byteasar is a famous safe-cracker, who renounced his criminal activity and got into testing and certifying anti-burglary devices. He has just received a new kind of strongbox for tests: a combinatorial safe. A combinatorial safe is something different from a combination safe, even though it is opened with a rotary dial. The dial can be set in different positions, numbered from 0 to n-1. Setting the dial in some of these positions opens the safe, while in others it does not. And here is the combinatorial property, from which the name comes from: if x and y are opening positions, then so is (x+y) mod n too; note that is holds for x=y as well.
    Byteasar tried k different positions of the dial: m1,m2….mk. The positions M1,M 2….Mk-1 did not open the safe, only the last position Mk did. Byteasar is already tired from checking these K positions and has thus absolutely no intention of trying the remaining ones. He would like to know however, based on what he already knows about the positions he tried, what is the maximum possible number of positions that open the safe. Help him by writing an appropriate program!

    有一个密码箱,0到n-1中的某些整数是它的密码。
    且满足,如果a和b都是它的密码,那么(a+b)%n也是它的密码(a,b可以相等)
    某人试了k次密码,前k-1次都失败了,最后一次成功了。
    问:该密码箱最多有多少不同的密码。

    Input

    The first line of the standard input gives two integers N and k, separated by a single space, (1<=K<=250000,k<=N<=10^14), The second line holds K different integers, also separated by single spaces, m1,m2….mk, 0<=Mi<N. You can assume that the input data correspond to a certain combinatorial safe that complies with the description above.
    In tests worth approximately 70% of the points it holds that k<=1000. In some of those tests, worth approximately 20% of the points, the following conditions hold in addition: N< 10 ^8 and K<=100.

    第一行n,k
    下面一行k个整数,表示每次试的密码
    保证存在合法解

    1<=k<=250000 k<=n<=10^14

    Output

    Your program should print out to the first and only line of the standard output a single integer: the maximum number of the dial's positions that can open the safe.

    一行,表示结果

    Sample Input

    42 5
    28 31 10 38 24

    Sample Output

    14
     

    假如x是密码,则所有gcd(x,n)的倍数就一定是密码,反之则一定不是(因为线性方程组的解)

    换言之,密码一定可以表示为x,2x,3x,4x,......其中x为n的一个约数

    推出了上面这些性质这道题就很好做了,首先最后一次试出来了说明x|gcd(a[k],n)

    且x又不能整除gcd(a[i],n),其中i<k

    所以我们暴力枚举所有可能的x,然后直接检验是否满足不能整除gcd(a[i],n)就可以了

     1 #include<cstring>
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<iostream>
     6 
     7 #define ll long long
     8 #define inf 1000000007
     9 #define N 1000007
    10 
    11 #define Wb putchar(' ')
    12 #define We putchar('
    ')
    13 #define rg register int
    14 using namespace std;
    15 inline ll read()
    16 {
    17     ll x=0,f=1;char ch=getchar();
    18     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    19     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    20     return x*f;
    21 }
    22 inline void write(ll x)
    23 {
    24     if(x<0) putchar('-'),x=-x;
    25     if (x==0) putchar(48);
    26     rg num=0;char c[20];
    27     while(x) c[++num]=(x%10)+48,x/=10;
    28     while(num) putchar(c[num--]);
    29 }
    30 
    31 ll n,k,ans;
    32 ll a[250001],cnt;  
    33 
    34 bool check(ll x)  
    35 {   
    36     for(rg i=1;i<=cnt;i++)  
    37         if(a[i]%x==0) return false;  
    38     return true;  
    39 }  
    40 ll gcd(ll a,ll b)  
    41 {  
    42     if(a==0) return b;  
    43     return gcd(b%a,a);  
    44 }  
    45 int main()  
    46 {  
    47      n=read(),k=read();  
    48     for(rg i=1;i<=k;i++)  
    49         a[i]=read();  
    50     ans=n;  
    51     for(rg i=1;i<=k;i++)  
    52         a[i]=gcd(n,a[i]);  
    53     sort(a+1,a+k);  
    54     for(rg i=1;i<k;i++)  
    55         if(a[i]!=a[i-1])  
    56         {  
    57             cnt++;  
    58             a[cnt]=a[i];  
    59         } 
    60     for(ll i=1;i<=sqrt(a[k]);i++)  
    61            if(a[k]%i==0)  
    62         {  
    63             if(check(i)) {ans=n/i;break;}  
    64             else if(check(a[k]/i)) ans=n/a[k]*i;  
    65         }  
    66     write(ans); 
    67 }
  • 相关阅读:
    Nginx 允许多个域名跨域访问
    mongo 命令
    PyTorch torch.cuda.device_count 返回值与实际 GPU 数量不一致
    APUE 学习笔记 —— 文件I/O
    Django transaction 误用之后遇到的一个问题与解决方法
    如何更新 CentOS 镜像源
    Supervisor 的安装与配置教程
    Sentry的安装搭建与使用
    Python, Django 性能分析工具的使用
    记一次 Apache HUE 优化之因使用 Python 魔术方法而遇到的坑
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8983598.html
Copyright © 2011-2022 走看看