題意:
給定n個數的序列
m個詢問,問該區間內,與所有區間內數互質的數有多少個
#include#include #include #include #include #define N 200005 using namespace std; vector prime[N];//prime[i] 是i的所有因子(不包括1) vector edge[N]; struct query{ int l, r, num; bool operator<(const query& a)const{ return a.l>l; } }q[N]; int ans[N]; int tree[N]; int l[N], r[N], vis[N]; int n, m, a[N]; int lowbit(int x){return x&(-x);} void add(int pos, int val){ while(pos){ tree[pos] += val; pos -= lowbit(pos); } } int getsum(int pos){ int ans = 0; while(pos <= n){ ans += tree[pos]; pos += lowbit(pos); } return ans; } void init(){ for(int i = 2; i < N; i++) for(int j = i; j < N; j+=i) prime[j].push_back(i); } int main(){ int i, j; init(); while(scanf("%d %d",&n,&m), n+m){ for(i = 1; i <= n; i++)scanf("%d",&a[i]); memset(vis, 0, sizeof(vis)); for(i = 1; i <= n; i++) { int pos = 0, siz = prime[a[i]].size(); for(j = 0; j < siz; j++) { pos = max(pos, vis[prime[a[i]][j]]); vis[prime[a[i]][j]] = i; } l[i] = pos; } memset(vis, 1, sizeof(vis)); for(i = n; i ; i--) { int pos = n+1, siz = prime[a[i]].size(); for(j = 0; j < siz; j++) { pos = min(pos, vis[prime[a[i]][j]]); vis[prime[a[i]][j]] = i; } r[i] = pos; } memset(tree, 0, sizeof(tree)); for(i = 1; i <= n; i++) { if(l[i]) edge[l[i]].push_back(i); else { add(i, 1); if(r[i]<=n) add(r[i], -1); } } for(i = 1; i <= m; i++)scanf("%d %d",&q[i].l,&q[i].r), q[i].num = i; sort(q+1, q+m+1); int num = 1; for(i = 1; i <= n; i++) { while(q[num].l == i) { ans[q[num].num] = getsum(q[num].l) - getsum(q[num].r+1); num++; } add(i, -1); if(r[i] <= n) add(r[i], 1); for(j = 0; j < edge[i].size(); j++) { int v = edge[i][j]; add(v, 1); if(r[v]<=n) add(r[v], -1); } edge[i].clear(); } for(i = 1; i<= m; i++)printf("%d\n", ans[i]); } return 0; }