【题解】CF_338D_GCD Table
solution:
猜到了结论,但是没有实力证明。
现在我把它证明出来了。
(i,j)=a_0, (i,j+1)=a_1
=>i=a_0x_0, j=a_0y_0, || i=a_1x_1, j+1=a_1y_1
=>lcm(a_0,a_1,…,a_n) | i
如果 i ≠ l c m ( a 0 , a 1 , . . . , a n ) i\ne lcm(a_0,a_1,...,a_n) i=lcm(a0,a1,...,an) ,设 i ′ = d ∗ l c m ( a 0 , a 1 , . . . , a n ) i'=d*lcm(a_0,a_1,...,a_n) i′=d∗lcm(a0,a1,...,an)
对任意的下标 l, i’=a_0x_0d, 因为 (x_0d,y_0)=1 成立,所以 (x_0,y_0)=1 也成立,故 i 也成立,所以取 i = l c m ( a 0 , a 1 , . . . , a n ) i=lcm(a_0,a_1,...,a_n) i=lcm(a0,a1,...,an) 最优。
现已知 j = a 0 y 0 j=a_0y_0 j=a0y0 , j ≡ 0 ( m o d a 0 ) j\equiv 0\pmod {a_0} j≡0(moda0)
一般的, j + l = a l y l j+l=a_ly_l j+l=alyl , j ≡ − l ( m o d a l ) j\equiv -l\pmod {a_l} j≡−l(modal)
扔进 excrt 中跑,可以得到 j ≡ x ( m o d l c m ( a 0 , a 1 , . . . , a n ) ) j\equiv x\pmod {lcm(a_0,a_1,...,a_n)} j≡x(modlcm(a0,a1,...,an)) ,注意必须 x x x 是正整数 。
现在得到 y l = i a l y_l=\frac{i}{a_l} yl=ali , x l = k i + x + l a l = k y l + x + l a l x_l=\frac{ki+x+l}{a_l}=ky_l+\frac{x+l}{a_l} xl=alki+x+l=kyl+alx+l , g c d ( x l , y l ) = g c d ( i a l , x + l a l ) gcd(x_l,y_l)=gcd(\frac{i}{a_l},\frac{x+l}{a_l}) gcd(xl,yl)=gcd(ali,alx+l) ,注意 x + l a l \frac{x+l}{a_l} alx+l 一定是一个正整数。(因为 x x x 一定是正整数)。
现在直接检验即可。时间复杂度 O(nloglcm) 。
注意点点细节,不要爆 longlong。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PII pair<int,int>
#define PIII pair<int,PII>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int mx=1e5+5;
int n;
ll a[mx],m[mx],r,c;
ll gcd(ll x,ll y) {
return y==0?x:gcd(y,x%y);
}
ll lcm(ll x,ll y) {
if(x==0||y==0) return x^y;
return x/gcd(x,y)*y;
}
void exgcd(ll &x,ll &y,ll a,ll b,ll &d) {
if(b==0) {
x=1,y=0,d=a;
}
else {
exgcd(y,x,b,a%b,d);
y-=x*(a/b);
}
}
bool excrt() {
for(int i=2;i<=n;i++) {
ll tmp=((a[i]-a[1])%m[i]+m[i])%m[i];
ll k1,k2,d; exgcd(k1,k2,m[1],m[i],d);
if(tmp%d) return 1;
k1=(k1%(m[i]/d)*(tmp/d)%(m[i]/d)+(m[i]/d))%(m[i]/d);
if(m[1]/d>c/m[i]) return 1;
ll M=m[1]/d*m[i];
a[1]=(a[1]+m[1]*k1%M)%M;
m[1]=M;
}
return 0;
}
signed main() {
// freopen("data.in","r",stdin);
static ll tm[mx];
scanf("%lld%lld%d",&r,&c,&n);
for(int i=1;i<=n;i++) {
scanf("%lld",&m[i]); tm[i]=m[i];
a[i]=(m[i]-(i-1)%m[i])%m[i];
}
if(excrt()) {
printf("NO");
return 0;
}
if(a[1]==0) a[1]+=m[1];
if(a[1]>r-n+1||m[1]>c) {
printf("NO");
return 0;
}
// cout<<m[1]<<" "<<a[1]<<endl;
for(int i=1;i<=n;i++) {
if(gcd(m[1]/tm[i],(a[1]+i-1)/tm[i])>1) {
printf("NO");
return 0;
}
}
printf("YES");
}

浙公网安备 33010602011771号