其他分享
首页 > 其他分享> > 2021江西 gym103366G. Magic Number Group

2021江西 gym103366G. Magic Number Group

作者:互联网

Magic Number Group

Tsiying has a sequence of positive integers with a length of n and quickly calculates all the factors of each number. In order to exercise his factor calculation ability, he has selected q consecutive subsequences from the sequence and found a positive integer p greater than 1 for each subsequence, so that p can divide as many numbers in this subsequence as possible. He has also found that p​ may have more than one.
So the question is, how many numbers in each subsequence can be divided at most?
Input
The first line contains an integer T (1≤T≤5×104), indicating that there is T​​ test cases next.
The first line of each test cases has two positive integers n​ (1≤n≤5×104​), q (1≤q≤5×104)​​​.
Next line n integers ai (1≤i≤n,1≤ai≤1×106), which representing the numbers in this sequence. The two adjacent numbers are separated by a space.
Each of the next q lines contains two integers l,r (1≤l≤r≤n), representing a subsequence being queried, al,al+1,⋯,ar, and l,r are separated by a space.
The input guarantees that the sum of n​ does not exceed 5×104​ and the sum of q​ does not exceed 5×104​.
Output
For each test case, output q lines, each line contains a positive integer, indicating the answer.

#include<bits/stdc++.h>
using namespace std;

#define read(x) scanf("%d",&x)
#define maxn ((int)5e4)
#define maxa ((int)1e6)

vector<int> prm;
int minP[maxa+5];
int u[maxa+5]; 	//质数的编号 

void getprime(int m) {	//8e4 
	for(int i=2;i<=m;i++) {
		if(minP[i]==0) {
			prm.push_back(i);
			minP[i]=i;
			u[i]=prm.size()-1;
		}
		for(int j=0;j<prm.size()&&prm[j]*i<=m;j++) {
			if(prm[j]>minP[i]) break;
			minP[prm[j]*i]=prm[j];
		}
	}
}

int n,q,cc;
int v[maxn+5];
vector<int> a[maxn+5];

struct Q{
	int l,r;
	int id;
	Q() {}
	Q(int _l,int _r,int _id) {l=_l,r=_r,id=_id;}
	bool operator < (const Q& e) const {
		return (l/cc==e.l/cc)?r<e.r:l<e.l;
	}
}; 
Q qry[maxn+5];

int cnt[maxa+5],num[maxn+5]; 	//cnt[prime] 该质数出现的次数 num[cnt] 出现次数为cnt的有几个质数 
int ans[maxn+5];

void add(int x,int& ans) {
	for(int i=0;i<a[x].size();i++) {
		int y=a[x][i];
		num[cnt[y]]--,num[++cnt[y]]++;
		ans=max(ans,cnt[y]);
	}
}

void del(int x,int& ans) {
	for(int i=0;i<a[x].size();i++) {
		int y=a[x][i];
		num[cnt[y]]--;
		if(!num[cnt[y]]&&ans==cnt[y]) --ans;
		num[--cnt[y]]++;
	}
}

int main() {
	getprime(maxa);
	
	int T;
	read(T);
	while(T--) {
		read(n),read(q);
		cc=sqrt(n);
		for(int i=1;i<=n;i++) read(v[i]);
		for(int i=1;i<=q;i++) {
			read(qry[i].l),read(qry[i].r),qry[i].id=i; 
			ans[i]=0;
		}
		sort(qry+1,qry+1+q);
		
		memset(num,0,sizeof(num));
		for(int i=1;i<=n;i++) {
			a[i].clear();
			
			int x=v[i];
			while(x!=1) {
				int y=minP[x];cnt[u[y]]=0;
				a[i].push_back(u[y]);
				while(x!=1&&x%y==0) x/=y;
			}
		}
		
		int L=1,R=0; //[L,R]
		for(int i=1;i<=q;i++) {
			int id=qry[i].id;
			ans[id]=ans[qry[i-1].id];
			int l=qry[i].l,r=qry[i].r;
			while(L<l) del(L++,ans[id]);
			while(L>l) add(--L,ans[id]);
			while(R<r) add(++R,ans[id]);
			while(R>r) del(R--,ans[id]);
		}
		
		for(int i=1;i<=q;i++) {
			printf("%d\n",ans[i]);
		}
	}
	
	return 0;
}

标签:cnt,Magic,int,gym103366G,Number,--,ans,qry,id
来源: https://blog.csdn.net/rabbit_ZAR/article/details/121216715