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;
}