感谢学长的板子
:https://blog.csdn.net/j2_o2/article/details/102677710
自己演了自己一天
参考代码
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
int n,dp[N][20],a[N];
struct hash_table {
ll hash_mod = 590027;
ll state[600000], ans[600000], up;
ll tot, first[600000], nxt[600000], w[600000];
void init() {
memset(first, 0, sizeof(first));
tot = 0;
up = 0;
}
ll ins(ll sta, ll val) {
ll key = sta%hash_mod;
for(ll i = first[key]; i; i = nxt[i]) {
if(state[w[i]] == sta) return ans[w[i]] += val;
}
state[++up] = sta;
ans[up] = val;
nxt[++tot] = first[key];
w[tot] = up;
first[key] = tot;
return val;
}
} mmp;
ll find(int key) {
for(ll k = 1; k <= mmp.up; ++k) {
ll sta = mmp.state[k];
ll w = mmp.ans[k];
if(sta==key)return w;
// printf("sta:%lld w%lld\n",sta,w);
}
return 0;
}
ll gcd(ll a,ll b) {
return (b==0)?a:gcd(b,a%b);
}
void ST() {
for(int j=1; (1<<j)<=n; j++) {
for(int i=1; i+(1<<j)-1<=n; i++) {
dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
}
}
int RMQ(int i,int j) {
int k=0;
while((1<<(k+1))<=j-i+1) k++;
return gcd(dp[i][k],dp[j-(1<<k)+1][k]);
}
void solve() {
for(int i=1; i<=n; i++) {
int l=i,r=n,temp=a[i];
while(l<=n) {
int L=l;
while(l<=r) {
int mid=(r - l)/2 + l;
if(RMQ(i,mid)==temp) {
l=mid+1;
} else {
r=mid-1;
}
}
//mmp[temp]+=(r-L+1);
mmp.ins(temp,(r-L+1));
temp=gcd(temp,a[l]);
r=n;
}
}
}
int main() {
int t;
scanf("%d",&t);
for(int T=1; T<=t; T++) {
mmp.init();
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
dp[i][0]=a[i];
}
ST();
solve();
int q;
scanf("%d",&q);
printf("Case #%d:\n",T);
while(q--) {
int x,l,r;
scanf("%d%d",&l,&r);
x = RMQ(l,r);
ll ans=find(x);
printf("%d %lld\n",x,ans);
}
}
return 0;
}
/*
1
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4
*/