Mys_C_K的质数集合计数好题 - 数论

定义F(n)为n中不同的质因子个数,求: i = 1 n 2 F ( i ) , n 10 12

首先考虑一个 O ( n 2 3 ) 的暴力,即 2 F ( i ) 是在枚举i的质因子集合的子集。那么改成枚举这个子集k,那么有恰好 n k 个数字包含这个集合,也就是:

A n s = k = 1 n μ 2 ( k ) n k

然后莫比乌斯函数平方的前缀和怎么求呢?继续考虑其意义,然后容斥,则:
i = 1 n μ 2 ( i ) = i = 1 n n i 2 μ ( i )

然后预处理一波就可以做到 O ( n 2 3 )

然后考虑用更数论的办法推:

F ( n ) = d | n μ 2 ( d ) = d | n k 2 | d m u ( k )

i = 1 n F ( i ) = i = 1 n d | i k 2 | d μ ( k ) = k = 1 n μ ( k ) k 2 | d n d

= k = 1 n μ ( k ) i = 1 n k 2 n k 2 i = k = 1 n μ ( k ) S ( n k 2 )

S ( n ) = i = 1 n n i 可以直接数论分 O ( n ) 块求。
复杂度为:
O ( i = 1 n n i 2 ) = O ( n i = 1 n 1 i ) = O ( n l g n )

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#define SN 1000010
#define lint long long
#define mod 1000000007
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int p[SN],mu[SN],notp[SN];
inline int prelude(int n)
{
    mu[1]=1;
    for(int i=2,c=0;i<=n;i++)
    {
        if(!notp[i]) p[++c]=i,mu[i]=-1;
        for(int j=1;j<=c&&p[j]<=n/i;j++)
        {
            int x=p[j]*i;notp[x]=1;
            if(i%p[j]) mu[x]=-mu[i];
            else { mu[x]=0;break; }
        }
    }
    return 0;
}
inline lint F(lint n,lint ans=0)
{
    for(lint s=1,t;s<=n;s=t+1) t=n/(n/s),ans+=(n/s)*(t-s+1);
    return ans%mod;
}
int main()
{
    lint n,ans=0,sn=1;scanf("%lld",&n);
    while((sn+1ll)*(sn+1)<=n) sn++;prelude(sn);
    for(int i=1;i<=n/i;i++) if(mu[i]) ans+=mu[i]*F(n/i/i);
    return !printf("%lld\n",ans=(ans%mod+mod)%mod);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81950917