笨蛋花的小窝qwq

笨蛋花的小窝qwq

“我要再和生活死磕几年。要么我就毁灭,要么我就注定铸就辉煌。如果有一天,你发现我在平庸面前低了头,请向我开炮。”

P2158 [SDOI2008]仪仗队

posted on 2018-05-19 18:44:06 | under 平时做题+数论 |

嗯,这个题是个数学题,好像没有那么难,但我当时就是不会。

首先这个题我们自然会想到要枚举斜率$qwq$.

也就是说对于每个$x/y$,只会为最终答案加一。

那么事实上,我们完全可以通过一次$O(n)$的模拟来枚举每个横坐标,然后套一层$O(n)$的枚举斜率,解释如下。

假设我们队伍看坐在坐标系里面,那么对于每个至少经过一个人的斜率$k$,总可以可以表示为既约分数$$\frac{w_1}{w_2} \quad\ gcd(w_1,w_2)=1$$

那么事实上也可以表示成如下:$$\frac{w_1*t}{w_2*t} \quad\ (t \in{Z})$$

两者的$k$完全相同,但是会重复计算,所以我们考虑用$O(n^2)$的时间记录一下并枚举来计算结果。

好像海星,但是太慢了,所以我们考虑这个题的数学本质。

倘若我们只枚举每一个横坐标,与之会对应的有$n$个纵坐标,组成$n$个二元组,那么我们只需要计算出有多少个二元组的横纵坐标互质即可。因为在这里我们选择将有效斜率集合的代表元记为既约分数的形式,所以如果一个点的横纵坐标仍有公因子,就肯定是重复的,所以不去管它。

那么现在很明确了,就是对于每个横坐标,记录它的$\phi$,求和即为有效答案。

但在这个地方有几个小细节:

1、枚举完横坐标之后把结果$\times{2}$,因为纵坐标也需要,枚举。

2、我们要从$2 $ ~ $ n-1$枚举,因为第一列和最后一行的人要特判。

3、最后要加上$3$,其中加$2$是因为位于第一列和最后一行没有计算进去,再加$1$是因为我们枚举$\phi$的时候是不会把$w1=w2$考虑在内的,所以要$+1$

那么接下来我们考虑如何求$\phi$

事实上,我们可以通过$n\sqrt{n}$的时间来枚举约数,从而推出每个$\phi$.但是在这里介绍线性推的方法——欧拉筛

实际上,与其说跟素数筛相似,不如说素数筛是借鉴的欧拉筛。对了,这个地方有一个误区,欧拉筛只针对于筛$\phi$。毕竟$\phi$的名字叫做欧拉函数嘛$qwq$.

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]];
        }
    }
}

类比线性筛而言,我们可以发现,对于一个素数$p$而言,$\phi(p)=p-1$,那么因为凡是素数必然在合数之前被筛到,所以我们可以考虑以此为基进行欧拉筛。那么,由于若$W=a\times{}{}b$且$gcd(a,b)=1$,就会有$\phi(W)=\phi(a)\times \phi(b)$,所可以有

else 
phi[i*prime[j]]=phi[i]*phi[prime[j]];

那么对于另一种情况而言,我们考虑有$$w=j^{n} \times {x}$$且其中$gcd(j^n,x)=1$

那么此时就会有$\phi(w)=\phi(j^n) \times \phi(x)$

而因为事实上$\phi(j^{n})=j^n-j^{n-1}$

所以会有$\phi(w)=\phi(x) \times j\times(j^{n-1}-j^{n-2})$

而这个$\phi(x) \times (j^{n-1}-j^{n-2})$即是我们当前枚举到的$\phi(i)$ .

所以:

if(i%prime[j]==0)
{
    phi[i*prime[j]]=prime[j]*phi[i];
    break;
}

$\color{red}by \ \ Flwer\_pks$