O(n*logn)预处理出对于每个位置i,最大的left[i], right[i], 使得arr[left[i]...i...right[i]]与arr[i]互质(当然arr[i]与其本身不互质不考虑),利用链表记录一些信息,然后用树状数组维护后缀和,更新答案。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
#include <bitset>
#include <iomanip>
//#pragma comment(linker, "/STACK:102400000,102400000")
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::stringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
using std::unique;
using std::lower_bound;
using std::random_shuffle;
using std::bitset;
using std::upper_bound;
using std::multiset;
using std::ios;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UN;
typedef pair<ULL, ULL> PAIR;
typedef multimap<int, int> MMAP;
typedef long double LF;
const int MAXN(200010);
const int MAXM(310);
const int MAXE(310);
const int MAXK(6);
const int HSIZE(131313);
const int SIGMA_SIZE(26);
const int MAXH(18);
const int INFI((INT_MAX-1) >> 1);
const ULL BASE(31);
const LL LIM(1e13);
const int INV(-10000);
const int MOD(1000000007);
const double EPS(1e-7);
const LF PI(acos(-1.0));
template<typename T> inline void checkmax(T &a, T b){if(b > a) a = b;}
template<typename T> inline void checkmin(T &a, T b){if(b < a) a = b;}
template<typename T> inline T ABS(const T &a){return a < 0? -a: a;}
struct BIT
{
int arr[MAXN], size;
void init(int s)
{
size = s;
memset(arr+1, 0, sizeof(arr[0])*s);
}
void updata(int ti, int tv)
{
for(; ti > 0; ti -= ti&-ti) arr[ti] += tv;
}
int query(int ti)
{
int ret = 0;
for(; ti <= size; ti += ti&-ti) ret += arr[ti];
return ret;
}
} bt;
struct EDGE
{
int u, v;
EDGE *next;
};
bool is[MAXN];
EDGE *rec[MAXN];
EDGE eg1[600100], *rear1;
void prepro()
{
memset(is, -1, sizeof(is));
is[1] = false;
for(LL i = 2; i <= 200000; ++i)
if(is[i])
{
rear1->v = i;
rear1->next = rec[i];
rec[i] = rear1++;
for(LL j = i+i; j <= 200000; j += i)
{
rear1->v = i;
rear1->next = rec[j];
rec[j] = rear1++;
is[j] = false;
}
}
}
int aid[MAXN], left[MAXN], right[MAXN];
int arr[MAXN];
EDGE *que[MAXN];
EDGE eg2[MAXN], *rear2;
EDGE *tab[MAXN];
EDGE eg3[MAXN], *rear3;
int ans[MAXN];
int main()
{
// freopen("d:\\in.txt","r",stdin);
// freopen("d:\\out.txt","w",stdout);
rear1 = eg1;
prepro();
int n, m;
while(scanf("%d%d", &n, &m), n+m)
{
rear2 = eg2;
rear3 = eg3;
int temp = 1;
for(int i = 1; i <= n; ++i)
{
scanf("%d", arr+i);
que[i] = tab[i] = 0;
checkmax(temp, arr[i]);
}
for(int i = 0; i <= temp; ++i) aid[i] = 0;
for(int i = 1; i <= n; ++i)
{
int mx = 0;
for(EDGE *p = rec[arr[i]]; p; p = p->next)
{
checkmax(mx, aid[p->v]);
aid[p->v] = i;
}
left[i] = mx+1;
}
for(int i = 0; i <= temp; ++i) aid[i] = n+1;
for(int i = n; i >= 1; --i)
{
int mi = n+1;
for(EDGE *p = rec[arr[i]]; p; p = p->next)
{
checkmin(mi, aid[p->v]);
aid[p->v] = i;
}
right[i] = mi-1;
rear3->u = left[i];
rear3->v = i;
rear3->next = tab[right[i]];
tab[right[i]] = rear3++;
}
int ql, qr;
for(int i = 0; i < m; ++i)
{
scanf("%d%d", &ql, &qr);
rear2->u = ql;
rear2->v = i;
rear2->next = que[qr];
que[qr] = rear2++;
}
bt.init(n);
for(int i = 1; i <= n; ++i) //更新答案时保证qr <= right[i]
{
if(left[i] > 1) bt.updata(left[i]-1, -1);
bt.updata(i, 1);
for(EDGE *p = que[i]; p; p = p->next) ans[p->v] = bt.query(p->u);
for(EDGE *p = tab[i]; p; p = p->next) //对于qr > right[k]的询问, arr[k]不会再有贡献了,所以修改回去
{
if(p->u > 1) bt.updata(p->u-1, 1);
bt.updata(p->v, -1);
}
}
for(int i = 0; i < m; ++i) printf("%d\n", ans[i]);
}
return 0;
}