D. CGCDSSQ(gcd性质)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. CGCDSSQ(gcd性质)相关的知识,希望对你有一定的参考价值。
考虑当 l l l作为子数组的左端点, 随着 r r r的增大, [ l , r ] [l,r] [l,r]的gcd是不增的
于是gcd会从 a [ l ] a[l] a[l]慢慢变小, 而且发现变小的次数不会很多, g c d gcd gcd变小后仍是自己的因子
考虑到 a [ l ] a[l] a[l]质因数分解后只有几十个质因子, 推测出变小次数只有几十次
也就是随着r的增大, 大部分时间gcd都是不变的
所以对于每个l, 找到会引起变化的关键点r1,r2,r3…即可
这样不太好找, 考虑固定r, 找之前会引起变小的l1,l2,l3…
这样我们可以利用r-1的那些答案.
也就是说如果存在一个x使得[x,r]和[x+1,r]的gcd不同, 必然存在
[x,r-1]和[x+1,r-1]的gcd不同. 因为[x+1,r]的gcd肯定是[x+1,r-1]的因子。
#include <iostream>
#include <map>
#include <vector>
using namespace std;
const int maxn = 3e5+10;
int n,a[maxn],q;
map<int,long long>mp;
vector<int>vec[maxn];
int gcd(int a,int b)
return b==0?a:gcd(b,a%b);
void solve(int id)
int now = a[id], pos = id;
for(int i=0;i<vec[id].size();i++)
mp[now] += pos-vec[id][i];
pos = vec[id][i];
now = gcd( now,a[pos] );
mp[now] += pos;
int main()
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++)
int now = a[i], ri = i;
if( gcd(now,a[i-1]) != now )
vec[i].push_back( i-1 ), now = gcd( now,a[i-1] );
for(int j=0;j<vec[i-1].size();j++)
int le = vec[i-1][j];
if( gcd( now,a[le] ) != now )
vec[i].push_back(le),now = gcd( now,a[le] );
for(int i=1;i<=n;i++) solve( i );
int q; cin >> q;
while( q-- )
int x; cin >> x;
cout << mp[x] << endl;
以上是关于D. CGCDSSQ(gcd性质)的主要内容,如果未能解决你的问题,请参考以下文章