Mr. Frog likes generating numbers! He can generate many numbers from a sequence.
For a given sequence a1,a2,⋯,ana1,a2,⋯,an Mr. Frog can choose two numbers l and r (1≤l≤r≤n1≤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 apap to vivi. 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≤500001≤n,q≤50000). which indicate the length of sequence and the number of modifications.
The second line contains n numbers:a1,a2,⋯,ana1,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≤10000001<≤ai≤1000000 all the time and the sum of all n and q is less than or equal to 2×1052×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. 题意:T组样例,给你一个长度为n的序列,q个询问,每个询问将pi这个位置的数改成vi,并输出当前序列中不同GCD的个数。
思路:我们首先预处理出整个区间不同GCD的个数,当我们修改一个位置的数时,我们考虑这个数对答案的影响,减去这个影响,改成新的数后再加上新的影响。
#include<map>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
int a[maxn],n;
ll ans;
map<int,ll> mp;
struct Node{
int gcd;
ll num;
Node(){}
};
struct node{
int l;
int r;
int sum;
}tree[maxn<<2];
void pushup(int cur)
{
tree[cur].sum=__gcd(tree[cur<<1].sum,tree[cur<<1|1].sum);
}
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
if(l==r)
{
tree[cur].sum=a[l];
return ;
}
int m=(l+r)>>1;
build(l,m,cur<<1);
build(m+1,r,cur<<1|1);
pushup(cur);
}
void update(int tar,int val,int cur)
{
if(tree[cur].l==tree[cur].r)
{
tree[cur].sum=val;
return ;
}
if(tar<=tree[cur<<1].r) update(tar,val,cur<<1);
else update(tar,val,cur<<1|1);
pushup(cur);
}
int queryleft(int L,int R,int val,int cur)
{
if(L<=tree[cur].l&&tree[cur].r<=R&&tree[cur].sum%val==0) return 0;
if(tree[cur].l==tree[cur].r) return tree[cur].l;
int res=0;
if(R>tree[cur<<1].r) res=queryleft(L,R,val,cur<<1|1);
if(L<=tree[cur<<1].r&&res==0) res=queryleft(L,R,val,cur<<1);
return res;
}
int queryright(int L,int R,int val,int cur)
{
if(L<=tree[cur].l&&tree[cur].r<=R&&tree[cur].sum%val==0) return 0;
if(tree[cur].l==tree[cur].r) return tree[cur].l;
int res=0;
if(L<=tree[cur<<1].r) res=queryright(L,R,val,cur<<1);
if(R>tree[cur<<1].r&&res==0) res=queryright(L,R,val,cur<<1|1);
return res;
}
void init()
{
int tmp,jmp,tgcd;
for(int i=1;i<=n;i++)
{
tmp=i,tgcd=a[i];
while(tmp<=n)
{
jmp=queryright(tmp,n,tgcd,1);
if(jmp==0) jmp=n+1;
if(!mp[tgcd]) ans++;
mp[tgcd]+=jmp-tmp;
tgcd=__gcd(tgcd,a[jmp]);
tmp=jmp;
}
}
}
void change1(int tar)
{
vector<Node> v1,v2;
int tmp,jmp,tgcd;
tmp=tar,tgcd=a[tar];
while(tmp>=1)
{
jmp=queryleft(1,tmp,tgcd,1);
Node x;
x.gcd=tgcd;
x.num=tmp-jmp;
v1.push_back(x);
tgcd=__gcd(tgcd,a[jmp]);
tmp=jmp;
}
tmp=tar,tgcd=a[tar];
while(tmp<=n)
{
jmp=queryright(tmp,n,tgcd,1);
if(jmp==0) jmp=n+1;
Node x;
x.gcd=tgcd;
x.num=jmp-tmp;
v2.push_back(x);
tgcd=__gcd(tgcd,a[jmp]);
tmp=jmp;
}
for(int i=0;i<v1.size();i++)
for(int j=0;j<v2.size();j++)
{
int num=v1[i].num*v2[j].num;
int gcd=__gcd(v1[i].gcd,v2[j].gcd);
if(!mp[gcd]) ans++;
mp[gcd]-=num;
if(!mp[gcd]) ans--;
}
}
void change2(int tar)
{
vector<Node> v1,v2;
int tmp,jmp,tgcd;
tmp=tar,tgcd=a[tar];
while(tmp>=1)
{
jmp=queryleft(1,tmp,tgcd,1);
Node x;
x.gcd=tgcd;
x.num=tmp-jmp;
v1.push_back(x);
tgcd=__gcd(tgcd,a[jmp]);
tmp=jmp;
}
tmp=tar,tgcd=a[tar];
while(tmp<=n)
{
jmp=queryright(tmp,n,tgcd,1);
if(jmp==0) jmp=n+1;
Node x;
x.gcd=tgcd;
x.num=jmp-tmp;
v2.push_back(x);
tgcd=__gcd(tgcd,a[jmp]);
tmp=jmp;
}
for(int i=0;i<v1.size();i++)
for(int j=0;j<v2.size();j++)
{
ll num=v1[i].num*v2[j].num;
int gcd=__gcd(v1[i].gcd,v2[j].gcd);
if(!mp[gcd]) ans++;
mp[gcd]+=num;
if(!mp[gcd]) ans--;
}
}
int main()
{
int t,q,tar,val;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
ans=0;
mp.clear();
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,n,1);
init();
printf("Case #%d:\n",cas);
while(q--)
{
scanf("%d%d",&tar,&val);
change1(tar);
update(tar,val,1);
a[tar]=val;
change2(tar);
printf("%lld\n",ans);
}
}
return 0;
}