ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

51nod1239 min25筛 欧拉函数前缀和

2019-08-30 12:43:50  阅读:409  来源: 互联网

标签:前缀 g0 int min25 积性 质数 51nod1239 ll


题意:n<=1e10 求phi(i)的前缀和

思路:定义g(n,j)=sum{i=1~n}g0(i)*[i的最小质因子>第j个质数 or i是质数]

考虑埃氏筛里每筛掉一个最小质因子带来的贡献来递推求g(n/i,j),滚动滚掉j那一维

要点就几个吧 phi(p)=p-1

所以将其分为g0(p)=p  h0(p)=1 两个完全积性函数来求每个g(n/i,|p|)跟g(n/i,0)

phi(p^k)=p^(k)-p^(k-1),接下来就是套板子的事情了

//min25筛求f前缀和 
//要求:积性函数+f(p)是多项式(或者是完全积性函数的和 )+ f(p^c)非常好求
//51nod 1239 欧拉函数前缀和 
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string.h>
using namespace std;
#define ll long long
const int N = 1e6+5;
const ll mod = 1e9+7;
ll Sqr,isp[N],pri[N],sump[N],tot,m,id1[N],id2[N],g[N],h[N];
ll w[N];
void init(int n){//线筛预处理质数 与质数的前缀和(f(p)的前缀和)
    isp[1]=1;
    for (int i=2;i<=n;++i){
        if (!isp[i]) pri[++tot]=i,sump[tot]=1ll*(sump[tot-1]+i)%mod;
        for (int j=1;i*pri[j]<=n;++j){
            isp[i*pri[j]]=1;
            if (i%pri[j]==0) break;
        }
    }
}

ll qmod(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b=b>>1;
    }return res;
}
int fpc(int p,int c){//f(p^c)
    
    return (qmod(p,c)-qmod(p,c-1)+mod)%mod;
}

int S(ll x,int y,ll n){//S(x,y)=sum{i=1~x}[i的最小质因子>=pri[y] ]*f(i);
    if (x<=1||pri[y]>x) return 0;
    int k=(x<=Sqr)?id1[x]:id2[n/x];
    ll res=(1ll*g[k]-h[k]-sump[y-1]+y-1);(res=res+mod)%mod;//A. res= g(n,|P|)-sum_{i=1~j}f(Pi),需要改
    //if (y==1) res+=2;//特判 f(2)=f(p)+2 其他题可删
    for (int i=y;i<=tot&&1ll*pri[i]*pri[i]<=x;++i){
        ll p1=pri[i],p2=1ll*pri[i]*pri[i];
        for (int e=1;p2<=x;++e,p1=p2,p2*=pri[i])
            (res+=(1ll*S(x/p1,i+1,n)*fpc(pri[i],e)%mod+fpc(pri[i],(e+1))))%=mod;//pri[i]^e 是f(pri[i]^e)的值,需要改
    }
    return res%mod;
}

//定义: g(x,p)=sum{i=1~x}[i的最小质因子>pri[p] or i是质数]g0(i) ,要求g0是完全积性函数,不是的话要分开求。 后面在A处会合并
void getg0(ll n){//对每个n/i 求 g(n/i,0);  其中n/i映射到 ++m
    memset(h,0,sizeof(h));
    m=0;Sqr=sqrt(n);
    for (ll i=1,j;i<=n;i=j+1){
        j=n/(n/i);w[++m]=n/i;//整数分块 ; 下标映射 ;
        if (w[m]<=Sqr) id1[w[m]]=m;
        else id2[n/w[m]]=m;

        //合数也当成质数求和 h0(i)=1 g0(i)=i 
        h[m]=(w[m]-1);
        g[m]=((w[m]+2)%mod)*((w[m]-1)%mod)%mod;
        if (g[m]&1) g[m]+=mod;g[m]/=2;
    }
}

void getgp(ll n){//对每个n/i 求g(n/i,|P|) h(n/i,|P|) 之前n/i映射到w[i]=n/i; 

    // g(x,p)=sum{i=1~x}[i的最小质因子>p or i是质数]g0(i)  ,其中g0(i)=i; 维护时省略第二维   f(p)=g0(p)-h0(p)凑完全积性 
    // h(x,p)=sum{i=1~x}[i的最小质因子>p or i是质数]h0(i)  ,其中h0(i)=1; 维护时省略第二维
    for (int j=1;j<=tot;++j)
        for (int i=1;i<=m&&1ll*pri[j]*pri[j]<=w[i];++i){
            int k=(w[i]/pri[j]<=Sqr)?id1[w[i]/pri[j]]:id2[n/(w[i]/pri[j])];//不用改

            g[i]=(g[i]-1ll*pri[j]*(g[k]-sump[j-1])%mod)%mod;g[i]=(g[i]+mod)%mod;//需要改 g(n,j)=g(n,j-1) -g0(pri[j])*[ (]g(k,j-1)-sum_{i=1~j-1}g0(pri[i]) ];
            h[i]=(h[i]-h[k]+j-1);h[i]=(h[i]+mod)%mod;                           //需要改 同上
        }
}

int main(){
    ll n;
    scanf("%lld",&n);
    Sqr=sqrt(n);init(Sqr);
    
    getg0(n);getgp(n);
    ll ans1=S(n,1,n)+1;
    printf("%lld\n",(ans1+mod)%mod);


    system("pause");
    return 0;
}

 

标签:前缀,g0,int,min25,积性,质数,51nod1239,ll
来源: https://blog.csdn.net/animalcoder/article/details/100154359

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有