这里附上题目链接:CF776B Sherlock and his girlfriend。
~~手动分割~~
题目
思路解析
其实这题的叙述就是在故弄玄虚。
- 由题,所有价格为质数的珠宝颜色都可以相同,所有价格为合数的珠宝颜色都可以相同。因为任意合数都不为其他所有合数的质因数。
- 所以,当1≤n≤2时,k=1;当3≤n时,k=2即最多使用两种不同颜色。
因此,
- 定义一个全局数组color[ ]存储每件珠宝的颜色。该数组初始化时所有元素皆为0。
- 使用筛法将区间
[2,n+1]
中所有的合数筛出,并将这些合数所对应的color[i]
赋为1。 - 因为题目所使用的颜色标记是从1开始的,所以在输出结果前,先将
color[2]
到color[n+1]
的元素都加一。
for(i=2;i<=n+1;i++)
{
++color[i];
}
1.欧拉筛法
AC代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int n,k;//共有n件珠宝,最少需要k种颜色
int color[100005];//存储每件珠宝的颜色
int prime_permutation[100005];//数组prime_permutation存储得到的素数
//欧拉筛法
int euler_sieve(int n)//n为右界
{
int i,j,sum=0;
for(i=2;i<=n;i++)
{
if(!color[i])//若i为质数
{
prime_permutation[sum]=i;
sum++;
}
for(j=0;j<sum&&(i*prime_permutation[j]<=n);j++)
{
color[i*prime_permutation[j]]=1;//将合数i*prime_permutation[j]筛去
if(i%prime_permutation[j]==0)
{
break;
}
}
}
return 0;
}
int main()
{
int i;
//输入数据
scanf("%d",&n);
//筛选素数
euler_sieve(n+1);//第i件珠宝的价格为i+1.因为有n件珠宝,所以右界为n+1
//预处理结果
if(n<3)
{
k=1;
}
else
{
k=2;
}
for(i=2;i<=n+1;i++)
{
++color[i];
}
//输出结果
printf("%d\n",k);
for(i=2;i<=n+1;++i)
{
printf("%d ",color[i]);
}
return 0;
}
2.埃氏筛法
AC代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int n,k;//共有n件珠宝,最少需要k种颜色
int color[100005];//存储每件珠宝的颜色
//埃氏筛法
int eratosthenes_sieve(int n)//n为右界
{
int i,j;
for(i=2;i<=n;i++)
{
if(!color[i])//若i为质数
{
for(j=2;j*i<=n;j++)
{
color[j*i]=1;
}
}
}
return 0;
}
int main()
{
int i;
//输入数据
scanf("%d",&n);
//筛选素数
eratosthenes_sieve(n+1);//第i件珠宝的价格为i+1.因为有n件珠宝,所以右界为n+1
//预处理结果
if(n<3)
{
k=1;
}
else
{
k=2;
}
for(i=2;i<=n+1;i++)
{
++color[i];
}
//输出结果
printf("%d\n",k);
for(i=2;i<=n+1;++i)
{
printf("%d ",color[i]);
}
return 0;
}