天天看点

HDU 5930 GCD

Mr. Frog likes generating numbers! He can generate many numbers from a sequence. 

For a given sequence 

a1,a2,⋯,an

a1,a2,⋯,an Mr. Frog can choose two numbers l and r (

1≤l≤r≤n

1≤l≤r≤n) and calculate the gcd between l-th and r-th number in this sequence 

g=gcd(al,al+1,⋯,ar)

g=gcd(al,al+1,⋯,ar). Asan expert in generating numbers, Mr. Frog wants to know how many distinct numbers can be generated by a sequence. 

Mr. Frog likes challenges, so there may be many modifications in this sequence. In the i-th modification, Mr. Frog may change 

ap

ap to 

vi

vi. After each modification, you are asked to tell how many distinct numbers can be generated by this sequence immediately! 

Input

The first line contains only one integer T, which indicates the number of test cases. 

For each test case, the first line includes two numbers n, q(

1≤n,q≤50000

1≤n,q≤50000). which indicate the length of sequence and the number of modifications. 

The second line contains n numbers:

a1,a2,⋯,an

a1,a2,⋯,an. 

Then q lines, each line contain two numbers, 

pi,vi(1≤pi≤n,1≤vi≤1000000)

pi,vi(1≤pi≤n,1≤vi≤1000000). 

Test data guarantee that 

1<≤ai≤1000000

1<≤ai≤1000000 all the time and the sum of all n and q is less than or equal to 

2×105

2×105. 

Output

For each test case, first output one line "Case #x:", where x is the case number (starting from 1). Then q lines, each line contain only one number, which is the answer to current sequence.

Sample Input

2
3 2
1 2 3
1 3
2 3

3 2
3 3 3
1 1
2 2      

Sample Output

Case #1:
3
1
Case #2:
2
3      

Hint

For case 1, after the first operation, 3,2,1 can be generated by the sequence 3, 2, 3. Whereas after the second operation, sequence 3, 3, 3 can generate only 3.

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
const int N = 2e5 + 10;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int low(int x) { return x&-x; }
int T, n, m,x,y;
int g[N],f[N*5],c[N];
int a[N],aa[N],A,b[N],bb[N],B;

int gcd(int x,int y) {
  return x%y?gcd(y,x%y):y;
}

void build(int x,int l,int r) {
  if (l == r) {
    scanf("%d",&c[r]);
    g[x] = c[r];
  }
  else {
    int mid = l+r>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    g[x] = gcd(g[x<<1],g[x<<1|1]);
  }
}

int get(int x,int l,int r,int ll,int rr) {
  if (ll<=l&&r<=rr) return g[x];
  int mid = l+r>>1;
  if (ll<=mid && rr>mid) {
    return gcd(get(x<<1,l,mid,ll,rr),get(x<<1|1,mid+1,r,ll,rr));
  } 
  else if (ll<=mid) {
    return get(x<<1,l,mid,ll,rr);
  }
  else if (rr>mid) {
    return get(x<<1|1,mid+1,r,ll,rr);
  }
  else return 0;
}

int findleft(int x,int l,int r,int u,int v) {
  if (r <= u) {
    if (gcd(g[x], v) == v) return 0;
    if (l == r) return r;
    int mid = l+r>>1;
    int k = findleft(x<<1|1,mid+1,r,u,v);
    if (k) return k;
    return findleft(x<<1,l,mid,u,v);
  }
  int mid = l+r>>1;
  if (u>mid) {
    int k = findleft(x<<1|1,mid+1,r,u,v);
    if (k) return k;
  }
  return findleft(x<<1,l,mid,u,v);
}

void getleft(int x) {
  int ed = get(1,1,n,1,x);
  A = 0;
  for (int i = c[x],j=x,k;j;j = k) {
    k = findleft(1,1,n,x,i);
    a[A] = j - k;
    aa[A++] = i;
    i = gcd(c[k],i);
  }
}

int findright(int x,int l,int r,int u,int v) {
  if (l >= u) {
    if (gcd(g[x], v) == v) return n + 1;
    if (l == r) return r;
    int mid = l + r>>1;
    int k = findright(x<<1,l,mid,u,v);
    if (k<=n) return k;
    return findright(x<<1|1,mid+1,r,u,v);
  }
  int mid = l+r>>1;
  if (u<=mid) {
    int k = findright(x<<1,l,mid,u,v);
    if (k<=n) return k;
  }
  return findright(x<<1|1,mid+1,r,u,v);
}

void getright(int x) {
  int ed = get(1,1,n,x,n);
  B = 0;
  for (int i = c[x],j=x,k;j<=n;j = k) {
    k = findright(1,1,n,x,i);
    b[B] = k - j;
    bb[B++] = i;
    i = gcd(c[k],i);
  }
}

void change(int x,int l,int r,int u,int v) {
  if (l==r) {
    g[x] = v;
    return;
  }
  int mid = l+r>>1;
  if (u<=mid) change(x<<1,l,mid,u,v);
  else change(x<<1|1,mid+1,r,u,v);
  g[x] = gcd(g[x<<1],g[x<<1|1]);
}

int main(){
  int cas = 1;
  for (scanf("%d",&T);T--;cas++) {
    scanf("%d%d",&n, &m);
    build(1,1,n);
    memset(f,0,sizeof(f));
    int ans = 0;
    for (int i = 1;i<=n;i++) {
      getleft(i);
      for (int j = 0;j<A;j++) {
        if (!f[aa[j]]) ans++;
        f[aa[j]] += a[j]; 
      }
    }
    printf("Case #%d:\n",cas);
    while (m--) {
      scanf("%d%d",&x,&y);
      getleft(x);
      getright(x);
      for (int j = 0;j<A;j++) {
        for (int k = 0;k<B;k++) {
          int t = gcd(aa[j],bb[k]);
          f[t] -= 1LL * a[j] * b[k];
          if (!f[t]) ans--;
        }
      }
      c[x] = y;
      change(1,1,n,x,y);
      getleft(x);
      getright(x);
      for (int j = 0;j<A;j++) {
        for (int k = 0;k<B;k++) {
          int t = gcd(aa[j],bb[k]);
          if (!f[t]) ans++;
          f[t] += 1LL * a[j] * b[k]; 
        }
      }
      printf("%d\n",ans);
    }
  }
  return 0;
}