• 《洛谷P5325 【模板】Min_25筛》


    第一道黑题,虽然是模板题~。

    Min25筛.

    将多项式转化$f(i) = i*(i - 1) ightarrow f(i) = i*i - i$。

    对所以对于后面的g = g2 - g1。定义g2 为关于i*i的函数,g1为关于i的函数。

    那么对于s出删去的实际是g2 - g1的j = 0时候的值,就是前缀和相减。

    注意取模~

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 1e6+5;
    const int M = 1e6+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    LL sum1[N],sum2[N],prime[N],id1[N],id2[N],g1[N],g2[N],w[N];
    LL n,Sqr,inv6 = 166666668,tot = 0,m = 0;//inv6 - 6的逆元
    bool flag[N];
    //sum1 - i^1的前缀和,sum2 - i^2的前缀和,prime - 存素数
    void init_prime()//线性筛
    {
        Sqr = sqrt(n);
        for(int i = 2;i <= Sqr;++i)
        {
            if(!flag[i])
            {
                prime[++tot] = i;
                sum1[tot] = (sum1[tot-1]+i)%Mod;
                sum2[tot] = (sum2[tot-1]+1LL*i*i%Mod)%Mod;
            }
            for(int j = 1;j <= tot && prime[j]*i <= Sqr;++j)
            {
                flag[i*prime[j]] = 1;
                if(i%prime[j] == 0) break;
            }
        }
    }
    LL f1(LL x)//F[i] = i的前缀和
    {
        x %= Mod;
        return (x + 1) * x / 2 % Mod;
    }
    LL f2(LL x)//F[i] = i^2的前缀和
    {
        x %= Mod;
        return x * (x + 1) % Mod * (2 * x % Mod + 1) % Mod * inv6 %Mod;
    }
    LL getid(LL x)//找到x的离散化对应位置
    {
        if(x <= Sqr) return id1[x];
        else return id2[n/x];
    }
    void init_g()
    {
        for(LL L = 1,r;L <= n;L = r+1)//预处理g(n,0)
        {
            r = (n/(n/L)),w[++m] = (n/L);
            g1[m] = f1(w[m])-1,g2[m] = f2(w[m])-1;//把1减去,因为1不满足。
            if(w[m] <= Sqr) id1[w[m]] = m;
            else id2[n/w[m]] = m;
        }
    }
    void init_DP()
    {
        for(int i = 1;i <= tot;++i){//预处理到sqrt(n),即tot即可
            for(int j = 1;j <= m && prime[i]*prime[i] <= w[j];++j){
                g1[j] = (g1[j] - prime[i] * (g1[getid(w[j] / prime[i])] - sum1[i-1]) % Mod + Mod)%Mod;
                g2[j] = (g2[j] - prime[i] * prime[i] % Mod *(g2[getid(w[j] / prime[i])] - sum2[i-1]) % Mod + Mod)%Mod;
             //   printf("g1 is %lld g2 is %lld
    ",g1[j],g2[j]);
            }
        }
    }
    LL S(LL x,int j)
    {
        if(prime[j] >= x) return 0;
        LL k = getid(x);
        LL ans = (g2[k] - g1[k] + Mod - ((sum2[j] - sum1[j]) + Mod) % Mod) % Mod;
        for(int i = j + 1;i <= tot && prime[i] * prime[i] <= x;++i)//枚举最小质因子
        {
            LL sp = prime[i];
            for(int e = 1;sp <= x;sp *= prime[i],++e)//枚举次数
                ans = (ans + sp % Mod * (sp % Mod -1) % Mod * (S(x / sp,i) + (e > 1)) % Mod) % Mod;
        }
        return ans;
    }
    void pre_work()
    {
        init_prime();
        init_g();
        init_DP();
    }
    int main()
    {
        n = read();
        pre_work();
        LL ans = (S(n,0) + 1)%Mod;//+1是f[1]
        printf("%lld
    ",ans);
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    linux 命令学习
    反编译学习一:Mac下使用dex2jar
    如何删除你的MacOS上的旧版本Java
    使用screen 遇到的多窗口
    dede简略标题调用标签
    JQ实现导航滚动到指定位置变色,并置顶
    JQ实现当前页面导航加效果(栏目页有效)
    wordpress首页调用指定分类下的文章
    作业1#python用列表实现多用户登录,并有三次机会
    python数据类型之间的转换
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13710008.html
Copyright © 2020-2023  润新知