Codeforces Round #630 (Div. 2) B. Composite Coloring(数论)
明明感觉以前好像写过,但是题目都看了两天。。。
https://codeforces.com/contest/1332/problem/B
题目大意:
给定n个合数(这些数字都在1000以内),给定m范围是【1,11】;
让我们用这11个数字给n染色,每一种颜色里面的数字的gcd都要>1;
注意:我们填充数字的时候,必须要一个一个填充,就是1填完了填2,不能1填完了填3。
不用最大或最小化操作,一直填的去就行了。
input
3
3
6 10 15
2
4 9
23
437 519 865 808 909 391 194 291 237 395 323 365 511 497 781 737 871 559 731 697 779 841 961
output
1
1 1 1
2
2 1
11
4 7 8 10 7 3 10 7 7 8 3 1 1 5 5 9 2 2 3 3 4 11 6
-
唯一分解定理:一个数字能够分解成若干个素数的乘积
-
题目也很巧妙,刚好11个数字,刚好1000以内的11个素数就可以把所有数分解完
-
所以我们就只需要合理安排数据的安放排列就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL N=200200,M=2002;
LL a[N],b[N],flag[N];
LL prime[]={2,3,5,7,11,13,17,19,23,29,31};
//唯一分解定理:一个数字能够分解成若干个素数的乘积
//31*31<=1000
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
memset(flag,0,sizeof flag);
LL n;
cin>>n;
for(LL i=1;i<=n;i++)
cin>>a[i];
LL sum=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<11;j++)
{
if(a[i]%prime[j]==0)
{
//当前的质数已经被定义过下标,直接使用
if(flag[j]!=0) b[i]=flag[j];
else
{
//当前的质数未被定义下标,在总数的位置上添加
flag[j]=++sum;
b[i]=flag[j];
}
break;
}
}
}
cout<<sum<<endl;
for(int i=1;i<=n;i++)
{
cout<<b[i]<<" ";
}
cout<<endl;
}
return 0;
}