• Luogu P3362 Cool loves shaxian 生成函数


    题意:

    定义f(i)=∑ k∣i k^d(i≤n),给出q个询问,每个询问询问区间[l,r]的f(i)的和。

    n<=1e7 d<=1e18 q<=5e4

    可以发现f(i)是个积性函数,那么我们就可以欧拉筛 O(n) 预处理出f(i),然后做个前缀和就行了。

    f(i)分为三种情况:

    1.i为素数 f(i)=i^d

    2.i%p[j]!=0 f(i*pj)=f(i)*f(p[j])

    3.i%p[j]==0 这个比较复杂,以下是f老板说的:我们要考虑的是i*p[j]比i多的约数是什么,假设i*p[j]是p[j]的k次,那多出来的约数都是p[j]^k再乘个数,否则已经被i包含了,那只要考虑这些数的贡献就行,也就是f(i*p[j]/p[j]^k)*(p[j]^k)^d

    //by zykykyk
    #include<cstdio>
    #include<ctime>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<cstring>
    #define rg register
    #define il inline
    #define vd void
    #define ll long long
    #define mod 1000000007
    #define maxn 10000010
    #define For(i,x,y) for (rg int i=(x);i<=(y);i++)
    #define Dow(i,x,y) for (rg int i=(x);i>=(y);i--)
    #define cross(i,k) for (rg int i=first[k];i;i=last[i])
    using namespace std;
    il ll max(ll x,ll y){return x>y?x:y;}
    il ll min(ll x,ll y){return x<y?x:y;}
    il ll read(){
        ll x=0;int ch=getchar(),f=1;
        while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
        if (ch=='-'){f=-1;ch=getchar();}
        while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,tot,q,x,P[maxn],minp[maxn],minpd[maxn],sum[maxn];
    bool vis[maxn];
    ll d;
    il int power(int x,ll y){
        int ans=1;
        for (;y;y>>=1,x=1ll*x*x%mod) if (y&1) ans=1ll*ans*x%mod;
        return ans;
    }
    il vd init(){
        n=read(),d=read(),q=read();
        sum[1]=1;
        For(i,2,n){
            if (!vis[i]) P[++tot]=minp[i]=i,minpd[i]=sum[i]=power(i,d),sum[i]=(sum[i]+1)%mod;
            for (int j=1;i*P[j]<=n&&j<=tot;j++){
                int k=i*P[j];
                vis[k]=1;
                if (i%P[j]==0){
                    minp[k]=minp[i]*P[j];
                    minpd[k]=1ll*minpd[i]*minpd[P[j]]%mod;
                    sum[k]=(sum[i]+1ll*minpd[k]*sum[k/minp[k]]%mod)%mod;
                    break;
                }
                else {
                    minp[k]=P[j];
                    minpd[k]=minpd[P[j]];
                    sum[k]=1ll*sum[i]*sum[P[j]]%mod;
                }
            }
        }
        For(i,2,n) (sum[i]+=sum[i-1])%=mod;
    }
    
    int l,r;
    il vd work(){
        while (q--){
            l=read(),r=read();
            printf("%d
    ",((sum[r]-sum[l-1])%mod+mod)%mod);
        }
    }
    
    int main(){
        init(),work();
    }
  • 相关阅读:
    约束布局ConstraintLayout看这一篇就够了
    1-9 最长连续递增子序列 (20 分)
    1-8 数组循环左移 (20 分)
    1-6 求链式线性表的倒数第K项 (20 分)
    CMD命令集(转自脚本之家)
    网卡、网关
    PHP Callable强制指定回调类型的方法
    PHP常用魔术方法(__invoke魔术方法)
    php 通过 yield 实现协程有什么使用场景
    PHP的yield是个什么玩意
  • 原文地址:https://www.cnblogs.com/zykykyk/p/8822122.html
Copyright © 2020-2023  润新知