zoukankan      html  css  js  c++  java
  • CodeForces 338D GCD Table

    D. GCD Table
    time limit per test  1 second
    memory limit per test  256 megabytes
    input standard input
    output standard output

    Consider a table G of size n × m such that G(i, j) = GCD(i, j) for all 1 ≤ i ≤ n, 1 ≤ j ≤ mGCD(a, b) is the greatest common divisor of numbers a and b.

    You have a sequence of positive integer numbers a1, a2, ..., ak. We say that this sequence occurs in table G if it coincides with consecutive elements in some row, starting from some position. More formally, such numbers 1 ≤ i ≤ n and 1 ≤ j ≤ m - k + 1 should exist that G(i, j + l - 1) = al for all 1 ≤ l ≤ k.

    Determine if the sequence a occurs in table G.

    Input

    The first line contains three space-separated integers nm and k (1 ≤ n, m ≤ 1012; 1 ≤ k ≤ 10000). The second line contains k space-separated integers a1, a2, ..., ak (1 ≤ ai ≤ 1012).

    Output

    Print a single word "YES", if the given sequence occurs in table G, otherwise print "NO".

    Examples
    input
    100 100 5
    5 2 1 2 1
    output
    YES
    input
    100 8 5
    5 2 1 2 1
    output
    NO
    input
    100 100 7
    1 2 3 4 5 6 7
    output
    NO
    Note

    Sample 1. The tenth row of table G starts from sequence {1, 2, 1, 2, 5, 2, 1, 2, 1, 10}. As you can see, elements from fifth to ninth coincide with sequence a.

    Sample 2. This time the width of table G equals 8. Sequence a doesn't occur there.

    数学问题 扩展中国剩余定理

    首先可以知道这个数列如果存在,它最早会出现在“所有a[]的lcm”这一行,而如果lcm行都没有,之后的行每个数都成倍扩大,更不可能出现目标数列。

    我们假设数列第一个元素在第x列,因为是在gcd表上,所以a[i]一定是x的因数,也就是$ x = a[i]*k $

    这个式子的形式看上去很熟悉? $ x equiv 0 (mod a[i])$

    像这样继续把每个式子都列出来:

    $x equiv 0 (mod a_{1})$
    $x+1 equiv 0 (mod a_{2})$
    $x+2 equiv 0 (mod a_{3})$
    $x+3 equiv 0 (mod a_{4})$
    $x+4 equiv 0 (mod a_{5})$

    这样就得到了一串$x equiv a[i]-i+1   (mod a_{i})$ 形式的同余方程。

    然后用中国剩余定理解就行……吗?注意到这些b[]可能并不是互质的,我们需要扩展中国剩余定理

    扩展中国剩余定理?听起来好帅

    实际上就是用扩展欧几里得合并中国剩余定理,消除不互质的模数之间的gcd的影响。

    我们知道中国剩余定理就是用扩展欧几里得算法推出来的,那么它实际上就是扩展·扩展·扩展欧几里得算法?

    一连串花式化简好麻烦的,用latex写公式更麻烦。

    推荐左转http://blog.csdn.net/clove_unique/article/details/54571216

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #define LL long long
     7 using namespace std;
     8 const int mxn=10010;
     9 LL read(){
    10     LL x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 LL ksmul(LL a,LL b,LL p){
    16     LL res=0;
    17     if(b<0)b=-b,a=-a;
    18     while(b){
    19         if(b&1)(res+=a)%=p;
    20         a<<=1;a%=p;
    21         b>>=1;
    22     }
    23     return res;
    24 }
    25 LL gcd(LL a,LL b){
    26     return (!b)?a:gcd(b,a%b);
    27 }
    28 LL exgcd(LL a,LL b,LL &x,LL &y){
    29     
    30     if(!b){x=1;y=0;return a;}
    31     LL tmp=exgcd(b,a%b,x,y);
    32     LL c=x;x=y;y=c-a/b*y;
    33     return tmp;
    34 }
    35 LL inv(LL a,LL b){
    36     LL x,y;
    37     exgcd(a,b,x,y);
    38     x=(x%b+b)%b;
    39     if(!x)x+=b;
    40     return x;
    41 }
    42 LL n,M,k,lcm;
    43 LL a[mxn],m[mxn],c[mxn];
    44 int main(){
    45     int i,j;
    46     n=read();M=read();k=read();
    47     for(i=1;i<=k;i++)a[i]=read();
    48     lcm=a[1];
    49     for(i=2;i<=k;i++){
    50         lcm=lcm/gcd(lcm,a[i])*a[i];
    51         if(lcm>n){printf("NO
    ");return 0;}
    52     }
    53     for(i=1;i<=k;i++)m[i]=a[i],c[i]=a[i]-i+1LL;
    54     LL m1=m[1],c1=c[1];
    55     for(i=2;i<=k;i++){
    56         LL m2=m[i],c2=c[i];
    57         LL tmp=gcd(m1,m2);
    58         if((c2-c1)%tmp){printf("NO
    ");return 0;}//无解
    59         LL m3=m1/tmp*m2,c3=inv(m1/tmp,m2/tmp);
    60         c3=ksmul(c3,(c2-c1)/tmp,m2/tmp);
    61         c3=ksmul(c3,m1,m3);
    62         c3=((c3+c1)%m3+m3)%m3;
    63         m1=m3;c1=c3;
    64     }
    65     if(!c1)c1+=m1;
    66     if(c1>M-k+1){printf("NO
    ");return 0;}
    67     for(int i=1;i<=k;i++){
    68         LL tmp=gcd(lcm,c1+i-1);
    69         if(tmp!=a[i]){printf("NO
    ");return 0;}
    70     }
    71     printf("YES
    ");
    72     return 0;
    73 }
  • 相关阅读:
    Oracle学习
    挑战练习11.5 恢复CrimeFragment的边距
    844. Backspace String Compare
    496. Next Greater Element I
    682. Baseball Game
    707. Design Linked List
    挑战练习10.6 实现高效的RecyclerView刷新
    挑战练习9.5 日期格式化
    挑战练习8.8 RecyclerView ViewType
    挑战练习6.5 限制作弊次数
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6814762.html
Copyright © 2011-2022 走看看