​link​

考虑当D. CGCDSSQ(gcd性质)_图论作为子数组的左端点, 随着D. CGCDSSQ(gcd性质)_c++_02的增大, D. CGCDSSQ(gcd性质)_#include_03的gcd是不增的

于是gcd会从D. CGCDSSQ(gcd性质)_图论_04慢慢变小, 而且发现变小的次数不会很多, D. CGCDSSQ(gcd性质)_i++_05变小后仍是自己的因子

考虑到D. CGCDSSQ(gcd性质)_图论_04质因数分解后只有几十个质因子, 推测出变小次数只有几十次

也就是随着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;
}
}