题目链接 :
题目大意:
给定a,b数组,求gcd(a1+bj,a2+bj,a3+bj,...,an+bj);
思路:
考虑到每个数都增加k,最大公因数有这样的性质
gcd(a,b)=gcd(|a-b|,a)
gcd满足交换律,可以从序列任何位置开始计算
则原式可转化为
gcd(a1+bj,a2+bj,a3+bj,...,an+bj)=gcd(a1+bj,|a2-a1|,|a3-a2|...|an-an-1|);
可以预处理出G=gcd(|a2-a1|,|a3-a2|...|an-an-1|);
每次计算gcd(a1+bj,G)即可。时间复杂度(nlogn)
代码:
- #include
- using namespace std;
- typedef long long ll;
- typedef pair<int,int> PII;
- const int N=2e5+10;
- ll a[N],b[N];
- ll gcd(ll n,ll m)
- {
- return m?gcd(m,n%m):n;
- }
- void solve()
- {
- 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);
- ll tmp=0;
- for(int i=2;i<=n;i++){
- tmp=gcd(tmp,abs(a[i]-a[i-1]));
- }
- ll res;
- for(int i=1;i<=m;i++){
- res=gcd(tmp,a[1]+b[i]);
- cout<
' '; - }
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- int t=1;
- while(t--) solve();
- }
总结:
别忘了gcd除了辗转相除法还有更相减损术,gcd的交换律蒸的很好用