BZOJ-3944-杜教筛

来源:互联网 发布:c语言用函数判断闰年 编辑:程序博客网 时间:2024/06/04 20:03

题目大意:

ni=1μ(i)ni=1ϕ(i)


题目解析:

杜教筛科普:

关于杜教筛: 
F(n)=if(i),存在g=f×II表示恒等函数,即g=d|nf(d) 
我们定义G(n)=ig(i) ,就可以得到F(n)=G(n)iF(ni) 
如果G(n)可以在一定时间内求解,那么我们最好情况下可以做到O(n23)的时间求解F(n)


前面那项需要快速求解,最好O(1),后面那项可以dfs求解;

ni=1d|iμ(d)=1=ni=1nij=1μ(j)

1=ni=1Sμ(ni)

Sμ(n)=1ni=2Sμ(ni)



ni=1d|iϕ(d)=ni=1i=ni=1nij=1ϕ(j)

n(n+1)2=ni=1Sϕ(ni)

Sϕ(n)=n(n+1)2ni=2Sϕ(ni)


AC代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<map>using namespace std;#define N 5000000#define LL long longint T,n;int p[N+3],prime[N+3];LL phi[N+3],mu[N+3];map <int,LL> ansphi,ansmu;void get(){    phi[1]=mu[1]=1;    for (int i=2;i<=N;++i)    {        if (!p[i])        {            prime[++prime[0]]=i;            phi[i]=i-1;            mu[i]=-1;        }        for (int j=1;j<=N&&i*prime[j]<=N;++j)        {            p[i*prime[j]]=1;            if (i%prime[j]==0)            {                phi[i*prime[j]]=phi[i]*prime[j];                mu[i*prime[j]]=0;                break;            }            else            {                phi[i*prime[j]]=phi[i]*phi[prime[j]];                mu[i*prime[j]]=-mu[i];            }        }    }    for (int i=1;i<=N;++i) phi[i]+=phi[i-1],mu[i]+=mu[i-1];}LL sumphi(LL n){    if (n<N) return phi[n];    if (ansphi[n]) return ansphi[n];    LL tmp;    if (n&1) tmp=(n+1)/2*n;    else tmp=n/2*(n+1);    for (int i=2,j=0;i<=n;i=j+1)    {        j=n/(n/i);        tmp-=sumphi(n/i)*(LL)(j-i+1);        if (j==n) break;    }    ansphi[n]=tmp;    return tmp;}LL summu(int n){    if (n<=N) return mu[n];    if (ansmu[n]) return ansmu[n];    LL tmp=1;    for (int i=2,j=0;i<=n;i=j+1)    {        j=n/(n/i);        tmp-=summu(n/i)*(LL)(j-i+1);        if (j==n) break;    }    ansmu[n]=tmp;    return tmp;}int main(){    get();    scanf("%d",&T);    while (T--)    {        scanf("%lld",&n);        printf("%lld %lld\n",sumphi(n),summu(n));    }}


原创粉丝点击