GCD HDU - 5930

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章