Codeforces Round #630 (Div. 2) B. Composite Coloring (数论)

题目传送门

题意:给n个合数(存在两大于1相乘等于ai的因数)将最大公因数大于1的数分为一组,求每个数在哪个组(m<=11)

思路:ai<=1000,由数论知识可知任意大于1的整数的最小的大于1的因数为素数,又该数为合数,必存在一个小于等于sqrt(ai)的因数,所以该素数在sqrt(1000)内。即求出sqrt(1000)的因数即可,经计算可知小于等于sqrt(1000)的因数刚好11个。正好满足。

#include<bits/stdc++.h>
using namespace std;
int pr[12];
void ss(int n){ //线性筛求素数 
	int vis[n+1]={};
	vis[0]=vis[1]=1;
	for(int i=2;i<=sqrt(n);i++)
		 if(!vis[i])
		 	for(int j=i*i;j<=n;j+=i) vis[j]=1;//printf("j=%d\n",j);
	int k=0;
	for(int i=2;i<=n;i++)
		if(!vis[i]) pr[++k]=i;
}
int main(){
	int t,n;
	ss(sqrt(1000));
	/*for(int i=1;i<=11;i++) cout<<pr[i]<<endl; */
	cin>>t;
	while(t--){
		cin>>n;
		int a[n+1],c[n+1]={},cnt=1;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=11;i++)
		{	int f=0;
			for(int j=1;j<=n;j++)
				if(a[j]%pr[i]==0&&!c[j])
						c[j]=cnt,f=1;
			if(f) cnt++;
		}
		cout<<cnt-1<<endl;
		for(int i=1;i<=n;i++)
			printf(i==n?"%d\n":"%d ",c[i]);
	}
	return 0;
}