P2158 [SDOI2008]仪仗队
嗯,这个题是个数学题,好像没有那么难,但我当时就是不会。
首先这个题我们自然会想到要枚举斜率
也就是说对于每个
那么事实上,我们完全可以通过一次
假设我们队伍看坐在坐标系里面,那么对于每个至少经过一个人的斜率
那么事实上也可以表示成如下:
两者的
好像海星,但是太慢了,所以我们考虑这个题的数学本质。
倘若我们只枚举每一个横坐标,与之会对应的有
那么现在很明确了,就是对于每个横坐标,记录它的
但在这个地方有几个小细节:
1、枚举完横坐标之后把结果
2、我们要从
3、最后要加上
那么接下来我们考虑如何求
事实上,我们可以通过
实际上,与其说跟素数筛相似,不如说素数筛是借鉴的欧拉筛。对了,这个地方有一个误区,欧拉筛只针对于筛
int cnt=1,prime[100001],phi[100001];
bool check[100001];
inline void init(int n)
{
for(int i=2;i<=n;i++
{
if(!check[i])
{
phi[i]=i-1;
prime[cnt++]=i;
}
for(int j=1;j<=cnt;j++)
{
if(prime[j]*i>n)break;
check[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=prime[j]*phi[i];
break;
}
else
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
类比线性筛而言,我们可以发现,对于一个素数
else
phi[i*prime[j]]=phi[i]*phi[prime[j]];
那么对于另一种情况而言,我们考虑有
那么此时就会有
而因为事实上
所以会有
而这个
所以:
if(i%prime[j]==0)
{
phi[i*prime[j]]=prime[j]*phi[i];
break;
}