【题解】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=dlcm(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} j0(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} jl(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)} jx(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");
}
posted @ 2021-08-22 12:15  仰望星空的蚂蚁  阅读(11)  评论(0)    收藏  举报  来源