• P5325 【模板】Min_25筛


    题目描述

    定义积性函数f(x)f(x),且f(p^k)=p^k(p^k-1) p是一个质数),求

    f(i) 的前缀和

    10^9+7109+7取模。

    输入格式

    一行一个整数nn。

    输出格式

    一个整数表示答案。

    输入输出样例

    输入 #1
    10
    
    输出 #1
    263
    
    输入 #2
    1000000000
    
    输出 #2
    710164413
    

    说明/提示

    f(1)=1,f(2)=2,f(3)=6,f(4)=12,f(5)=20f(1)=1,f(2)=2,f(3)=6,f(4)=12,f(5)=20

    f(6)=12,f(7)=42,f(8)=56,f(9)=72,f(10)=40f(6)=12,f(7)=42,f(8)=56,f(9)=72,f(10)=40

    SOLUTION:

    洛谷的题解和网上的题解中求S()的时候是不同的

    我用的是网上的方法

    https://www.cnblogs.com/zhoushuyu/p/9187319.html

    https://www.luogu.org/problemnew/solution/P5325

    CODE:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define int long long
    using namespace std;
    const ll MOD=1000000007,inv2=500000004,inv3=333333336;
    ll prime[1000005],num,sp1[1000005],sp2[1000005];
    ll n,Sqr,tot,g1[1000005],g2[1000005],w[1000005],ind1[1000005],ind2[1000005];
    bool flag[1000005];
    void pre(int n)//预处理,线性筛
    {
        flag[1]=1;
        for(int i=1;i<=n;i++)
        {
            if(!flag[i])
            {
                prime[++num]=i;
                sp1[num]=(sp1[num-1]+i)%MOD;
                sp2[num]=(sp2[num-1]+1ll*i*i)%MOD;
            }
            for(int j=1;j<=num&&prime[j]*i<=n;j++)
            {
                flag[i*prime[j]]=1;
                if(i%prime[j]==0)break;
            }
        }
    }
    ll S(ll x,int y)//第二部分
    {
        if(x<=1||prime[y]>x)return 0;
        ll k=x<=Sqr?ind1[x]:ind2[n/x];
        ll ans=(g2[k]-g1[k]+MOD-(sp2[y-1]-sp1[y-1])+MOD)%MOD;
    
        for(int i=y;i<=num&&prime[i]*prime[i]<=x;i++)
        {
            ll p1=prime[i],p2=1ll*prime[i]*prime[i];
    		for (int e=1;p2<=x;++e,p1=p2,p2*=prime[i])
                ans+=((1ll*S(x/p1,i+1)*p1%MOD*(p1-1)%MOD)%MOD+1ll*p2%MOD*((p2-1)%MOD)%MOD),
    			ans%=MOD;
    
    
    
            /*
            ll pe=prime[i];
            for(int e=1;pe<=x;e++,pe=pe*prime[i])
            {
                ll xx=pe%MOD;
                ans=(ans+xx*(xx-1)%MOD*(S(x/pe,i)+(e!=1)))%MOD;
            }*/
        }
        return ans%MOD;
    }
    signed main()
    {
        scanf("%lld",&n);
        Sqr=sqrt(n);
        pre(Sqr);
        for(ll i=1;i<=n;)
        {
            ll j=n/(n/i);
            w[++tot]=n/i;
            g1[tot]=w[tot]%MOD;
            g2[tot]=g1[tot]*(g1[tot]+1)/2%MOD*(2*g1[tot]+1)%MOD*inv3%MOD;
            g2[tot]--;
            g1[tot]=g1[tot]*(g1[tot]+1)/2%MOD-1;
            if(n/i<=Sqr)ind1[n/i]=tot;
            else ind2[n/(n/i)]=tot;
            i=j+1;
        }//g1,g2分别表示一次项和二次项,ind1和ind2用来记录这个数在数组中的位置
        for(int i=1;i<=num;i++)//由于g数组可以滚动,所以就只开了一维
        {
            for(int j=1;j<=tot&&prime[i]*prime[i]<=w[j];j++)
            {
                ll k=w[j]/prime[i]<=Sqr?ind1[w[j]/prime[i]]:ind2[n/(w[j]/prime[i])];
                g1[j]-=prime[i]*(g1[k]-sp1[i-1]+MOD)%MOD;
                g2[j]-=prime[i]*prime[i]%MOD*(g2[k]-sp2[i-1]+MOD)%MOD;
                g1[j]%=MOD,g2[j]%=MOD;
                if(g1[j]<0)g1[j]+=MOD;
                if(g2[j]<0)g2[j]+=MOD;
            }
        }
        printf("%lld
    ",(S(n,1)+1)%MOD);
        return 0;
    }
    

      

    对于30\%30%的数据,保证1le nle 10^61n106。

    对于100\%100%的数据,保证1le nle 10^{10}1n1010

  • 相关阅读:
    asm volatile (&quot;B .&quot;)
    最大熵学习笔记(一)预备知识
    12、Cocos2dx 3.0游戏开发找小三之3.0中的生命周期分析
    Android中通过反射来设置Toast的显示时间
    Linux Centos7 Apache 訪问 You don&#39;t have permission to access / on this server.
    校园双选会,你都懂么
    关于虚继承和析构函数的一个奇怪的问题
    Codeforces Round #252 (Div. 2)B. Valera and Fruits
    P3809 【模版】后缀排序
    752. [BJOI2006] 狼抓兔子
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11338886.html
Copyright © 2020-2023  润新知