F - Rectangle GCD

https://atcoder.jp/contests/abc254/tasks/abc254_f

gcd 有个优美的性质,\(\gcd(a,b)=\gcd(b,a-b)\)

证明:

不妨设 \(a\ge b\)\(\gcd(a,b)=d,a=b+c\)

显然有 \(c=a-b\)\(\dfrac{c}{d}=\dfrac{a}{d}-\dfrac{b}{d}\)

所以 \(d|c\),所以 \(d|a-b\)

那么考虑数归不断扩展,对于 \(n\) 个数就有 \(\gcd(a_1,a_2,...,a_n)=\gcd(a_1,a_2-a_1,...,a_n-a_{n-1})\)

证明考虑 \(\gcd(a_1,a_2)=\gcd(a_2,a_1)=\gcd(a_1,a_2-a_1)\),又考虑 \(\gcd\) 有可并性,操作下去即可。

那么这道题就做完了。

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=(int)(2e5+5);
int n,q,a[N],b[N],c[N],d[N],f1[20][N],f2[20][N];

int gcd(int x,int y) {
	return !y?x:gcd(y,x%y);
}

int get1(int l,int r) {
	int qwq=log2(r-l+1);
	return gcd(f1[qwq][l],f1[qwq][r-(1ll<<qwq)+1]);
}

int get2(int l,int r) {
	int qwq=log2(r-l+1);
	return gcd(f2[qwq][l],f2[qwq][r-(1ll<<qwq)+1]);
}

signed main() {
	cin.tie(0); ios::sync_with_stdio(false);
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=2;i<=n;i++) c[i]=abs(a[i]-a[i-1]),d[i]=abs(b[i]-b[i-1]);
//	cout<<"xgf";
	for(int i=1;i<=n;i++) f1[0][i]=c[i];
	
	for(int i=1;(1ll<<i)<=n;i++)
		for(int j=2;j+(1ll<<i)-1<=n;j++) {
//			cout<<f1[i-1][j]<<" "<<f1[i-1][j+(1ll<<(i-1))]<<'\n';
			f1[i][j]=gcd(f1[i-1][j],f1[i-1][j+(1ll<<(i-1))]);
		}
	for(int i=1;i<=n;i++) f2[0][i]=d[i];
	for(int i=1;(1ll<<i)<=n;i++)
		for(int j=2;j+(1ll<<i)-1<=n;j++)
			f2[i][j]=gcd(f2[i-1][j],f2[i-1][j+(1ll<<(i-1))]);
//	cout<<"xgf";
	while(q--) {
		int x,y,xx,yy;
		cin>>x>>xx>>y>>yy;
		int res=a[x]+b[y]; 
		if(y+1<=yy) res=gcd(res,get2(y+1,yy));
		if(x+1<=xx) res=gcd(res,get1(x+1,xx));
		cout<<res<<'\n';
	}
	return 0;
}
posted @ 2022-07-13 16:47  FxorG  阅读(39)  评论(0编辑  收藏  举报