线筛 初见

o(n)的复杂度,筛出各种神奇。

 

bzoj2190仪仗队

 思路:线筛求欧拉函数。

#include<iostream>

#include<cstdio>

using namespace std;

int phi[40001]={0},prime[40001]={0};

bool flag[40001]={false};

void work(int n)

{

    int i,j;

    for (i=2;i<=n;++i)

    {

        if (!flag[i])

        {

            ++prime[0];prime[prime[0]]=i;phi[i]=i-1;

        }

        for (j=1;j<=prime[0]&&i*prime[j]<=n;++j)

        {

            flag[prime[j]*i]=true;

            if (i%prime[j]==0)

            {

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

            }

            else phi[i*prime[j]]=phi[i]*(prime[j]-1);

        }

    }

}

int main()

{

    int n,ans=0,i;

    scanf("%d",&n);

    work(n);

    for (i=2;i<n;++i)

        ans+=phi[i]*2;

    ans+=3;

    if (n==1) printf("1\n");

    else printf("%d\n",ans);

}
View Code

 

某次题目:

题目大意:输入n,求多少个正整数对x,y满足(1/x)+(1/y)=1/(n!)。

思路:对原式进行数学化简:n!=xy/(x+y),再化简一下:x=yn!/(y-n!),设a=n!,有x=ya/(y-a),令b=y-a,x=a(a+b)/b=a^2/b+a。因为x、y、a、b都是整数,所以b是a^2的约数,所以答案就是a^2约数个数个。(code中用了一个小技巧,穷举质因数,求质因数在n!中出现的个数,再共享给答案。可能会快。)

#include<iostream>

#include<cstdio>

#define P 1000000007

#define maxnode 1000005

using namespace std;

bool flag[maxnode]={false};

int prime[maxnode]={0};

void yu(int n)

{

    int i,j;

    for (i=2;i<=n;++i)

    {

        if (!flag[i])

            prime[++prime[0]]=i;

        for (j=1;j<=prime[0]&&i*prime[j]<=n;++j)

        {

            flag[i*prime[j]]=true;

            if (i%prime[j]==0) break;

        }

    }

}

int main()

{

    long long ans;

    int i,j,t,n,k;

    scanf("%d",&n);

    yu(n);ans=1;

    for (i=1;i<=prime[0];++i)

    {

        k=0;

        for (j=1;j*prime[i]<=n;++j)

        {

            t=j*prime[i];

            while(t%prime[i]==0)

            {

                ++k;t/=prime[i];

            }    

        }

        ans=(ans*(long long)(2*k+1))%P;

    }

    printf("%d\n",(int)ans);

}
View Code

 

你可能感兴趣的:(线筛 初见)