赞
踩
首先先把结论写出来。
g
c
d
(
a
,
b
)
=
g
c
d
(
a
,
b
−
a
)
gcd(a,b)=gcd(a,b−a)
gcd(a,b)=gcd(a,b−a)
g
c
d
(
a
,
b
,
c
)
=
g
c
d
(
a
,
b
−
a
,
c
−
b
)
gcd(a,b,c)=gcd(a,b−a,c−b)
gcd(a,b,c)=gcd(a,b−a,c−b)
g
c
d
(
a
1
,
a
2
,
…
a
n
)
=
g
c
d
(
a
1
,
a
2
−
a
1
,
…
a
n
−
a
n
−
1
)
gcd(a_1,a_2,…a_n)=gcd(a_1,a_2−a_1,…a_n−a_{n−1})
gcd(a1,a2,…an)=gcd(a1,a2−a1,…an−an−1)
例题1:Codeforces Round #691 (Div. 2)—C. Row GCD
C. Row GCD
题
意
:
给
你
两
个
数
组
a
和
b
,
对
于
j
=
1
,
.
.
.
,
m
,
找
出
a
1
+
b
j
,
.
.
.
,
a
n
+
b
j
的
g
c
d
.
题意:给你两个数组a和b,对于j=1,...,m,找出a_1+b_j,...,a_n+b_j的gcd.
题意:给你两个数组a和b,对于j=1,...,m,找出a1+bj,...,an+bj的gcd.
题解:根据上面的结论可得:
g
c
d
(
(
a
1
+
b
j
)
,
(
a
2
+
b
j
)
,
.
.
.
,
(
a
n
+
b
j
)
)
=
g
c
d
(
a
1
+
b
j
,
a
2
−
a
1
,
.
.
.
,
a
n
−
a
n
−
1
)
.
gcd((a_1+b_j),(a_2+b_j),...,(a_n+b_j))=gcd(a_1+b_j,a_2−a_1,...,a_n−a_{n−1}).
gcd((a1+bj),(a2+bj),...,(an+bj))=gcd(a1+bj,a2−a1,...,an−an−1).
所以我们先对a数组求出他差分数组的gcd,设他为d 也就是
d
=
g
c
d
(
a
2
−
a
1
,
a
3
−
a
2
,
.
.
.
.
,
a
n
−
a
n
−
1
)
;
d=gcd(a_2-a_1,a_3-a_2,....,a_n-a_{n-1});
d=gcd(a2−a1,a3−a2,....,an−an−1);
所以我们每次求
g
c
d
(
a
1
+
b
j
,
g
c
d
(
d
)
)
gcd(a_1+b_j,gcd(d))
gcd(a1+bj,gcd(d))
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+10; #define int long long int a[maxn],b[maxn]; signed main() { ios::sync_with_stdio(false); int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++) cin>>b[i]; //sort(a+1,a+n+1); int gcd=a[2]-a[1]; if(n==1) gcd=0; for(int i=2;i<=n;i++){ gcd=__gcd(gcd,a[i]-a[i-1]); } for(int i=1;i<=m;i++){ cout<<abs(__gcd(gcd,a[1]+b[i]))<<" "; } }
例题2:牛客小白月赛16 —小阳的贝壳
小阳的贝壳
g
c
d
(
a
1
,
a
2
,
…
a
n
)
=
g
c
d
(
a
1
,
a
2
−
a
1
,
…
a
n
−
a
n
−
1
)
gcd(a_1,a_2,…a_n)=gcd(a_1,a_2−a_1,…a_n−a_{n−1})
gcd(a1,a2,…an)=gcd(a1,a2−a1,…an−an−1)
题解:
图片来自巨雨的题解。
维护这个数组的差分序列。
操作一:因为是个差分数组,我们只需要给l端点加x,r+1端点的值-x即可。
操作二:我们只有得到这个差分数组的最大值即可。(不要忘记abs)
操作三:
求
g
c
d
(
a
l
,
a
l
+
1
,
…
a
r
)
=
g
c
d
(
a
l
,
a
l
+
1
−
a
l
,
…
a
r
−
a
r
−
1
)
gcd(a_l,a_{l+1},…a_r)=gcd(a_l,a_{l+1}−a_l,…a_r−a_{r−1})
gcd(al,al+1,…ar)=gcd(al,al+1−al,…ar−ar−1)
设
k
=
g
c
d
(
a
l
+
1
−
a
l
,
…
a
r
−
a
r
−
1
)
k=gcd(a_{l+1}−a_l,…a_r−a_{r−1})
k=gcd(al+1−al,…ar−ar−1)
也就是求
g
c
d
(
a
l
,
k
)
;
即
可
gcd(a_l,k);即可
gcd(al,k);即可
查询
a
l
a_l
al也就是查询差分数组
1
−
l
1-l
1−l的和。
也就是相当于单点修改 区间查询。
#include<bits/stdc++.h> #define ll long long using namespace std; #define endl '\n' #define int long long const int maxn=1e5+10; int a[maxn<<2]; int imax[maxn<<2]; int gcd[maxn<<2]; int sum[maxn<<2]; void push_up(int node){ sum[node]=sum[node*2+1]+sum[node*2]; gcd[node]=__gcd(gcd[node*2+1],gcd[node*2]); imax[node]=max(imax[node*2],imax[node*2+1]); } void build(int node,int start,int ends){ if(start==ends){ sum[node]=a[start]; gcd[node]=abs(a[start]); imax[node]=abs(a[start]); return ; } int mid=(start+ends)/2; build(node*2,start,mid); build(node*2+1,mid+1,ends); push_up(node); } void update(int node,int start,int ends,int pos,int val){ if(start==ends){ sum[node]+=val; gcd[node]=abs(sum[node]); imax[node]=abs(sum[node]); return ; } int mid=(start+ends)/2; if(pos<=mid) update(node*2,start,mid,pos,val); else update(node*2+1,mid+1,ends,pos,val); push_up(node); } int get_sum(int node,int start,int ends,int l,int r){ if(start>=l&&ends<=r){ return sum[node]; } int ans=0; int mid=(start+ends)/2; if(l<=mid) ans+=get_sum(node*2,start,mid,l,r); if(mid<r) ans+=get_sum(node*2+1,mid+1,ends,l,r); return ans; } int get_imax(int node,int start,int ends,int l,int r){ if(start>=l&&ends<=r){ return imax[node]; } int mid=(start+ends)/2; int ans=-1e15; if(l<=mid) ans=max(ans,get_imax(node*2,start,mid,l,r)); if(mid<r) ans=max(ans,get_imax(node*2+1,mid+1,ends,l,r)); return ans; } int get_gcd(int node,int start,int ends,int l,int r){ if(start>=l&&ends<=r){ return gcd[node]; } int mid=(start+ends)/2; int ans=0; if(l<=mid) ans=__gcd(ans,get_gcd(node*2,start,mid,l,r)); if(mid<r) ans=__gcd(ans,get_gcd(node*2+1,mid+1,ends,l,r)); return ans; } signed main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=n;i>=1;i--){ a[i]=a[i]-a[i-1]; } build(1,1,n); for(int i=0;i<m;i++){ int opt,l,r,x; cin>>opt; if(opt==1){ cin>>l>>r>>x; update(1,1,n,l,x); if(r+1<=n) update(1,1,n,r+1,-x); } else if(opt==2){ cin>>l>>r; if(l==r){ cout<<0<<endl; continue; } int ans=get_imax(1,1,n,l+1,r); cout<<ans<<endl; } else if(opt==3){ cin>>l>>r; if(l==r) cout<<get_sum(1,1,n,1,l)<<endl; else{ x=get_sum(1,1,n,1,l); cout<<__gcd(x,get_gcd(1,1,n,l+1,r))<<endl; } } } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。