【Codeforces】338 D GCD Table 中国剩余定理(孙子定理)

GCD Table
Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u
Submit

Status
Description
Consider a table G of size n × m such that G(i, j) = GCD(i, j) for all 1 ≤ i ≤ n, 1 ≤ j ≤ m. GCD(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 n, m 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”.

Sample Input
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
Hint
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.

題意:GCD(i , j + r - 1) = a[r] (k>=r >=1)
思路:
1. J % a[1] = 0
(J + 1) % a[2] = 0
……
(J + k - 1) % a[k] = 0

  1. I % a[i] = 0;
  2. 中国剩余定理分别算I,J,在检验

互质的中国剩余定理[从假设可知,对任何 ,由于 ,所以 这说明存在整数 使得 这样的 叫做 模 的数论倒数。考察乘积 可
满足:
lcm/m[i]*t(inverse)*a[i]

本题
不互质的

#include<iostream>
#include<stdio.h>
#define LL long long
using namespace std;
const int maxn=10005;
LL n,m,a[maxn],b[maxn];
int k;
LL gcd(LL a,LL b)
{
    if(!b)return a;
    return gcd(b,a%b);
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    LL r=exgcd(b,a%b,x,y),x0=x;
    x=y;
    y=x0-(a/b)*y;
    return r;
}
LL china(LL *m,LL *a)
{
    LL lcm=1,X=m[1],Y=a[1];
    for(int i=1;i<=k;i++)
    lcm=lcm/gcd(lcm,m[i])*m[i];
    for(int i=2;i<=k;i++)
    {   
        LL A=X,B=m[i],d,x,y,c=a[i]-Y;   
        d=exgcd(A,B,x,y);   
        if(c%d)
        return -1;      
        LL mod=m[i]/d;
        LL K=((x*c/d)%mod+mod)%mod;
        Y=X*K+Y;
        X=X*m[i]/d;
    }
    if(Y==0)
    return lcm;
    return Y;
}
bool check()
{
    LL I=china(a,b),J;
    if(I>n || I<=0)return false;
    for(int i=1;i<=k;i++)b[i]=1-i;
    J=china(a,b); 
    if(J+k-1>m || J<=0)return false;
    for(int i=1;i<=k;i++)if(gcd(I,J+i-1)!=a[i])return false;
    return true;
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++)
    cin>>a[i];
    if(check())cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值