zoukankan      html  css  js  c++  java
  • 洛谷3768:简单的数学题——题解

    https://www.luogu.org/problemnew/show/P3768

    题面来自洛谷,因为没用markdown所以直接截的图。

    剩余的图是我用markdown写完然后截的图。

    参考洛谷第一篇题解。

    这个式子直观感受就需要莫比乌斯反演,大致的过程参考:BZOJ2693:jzptab

    那么跳过暴力推式子,我们能够得到:

    (如果你疑问为什么是miu(k/d)而不是miu(d),其实二者皆可,但是为什么这么干请往下看)

    显然可以分块O(sqrt(n))做,那么后面的那一串东西怎么做呢?

    参考jzptab的想法的话我们知道后面的式子是积性函数可以O(n)筛出来。

    emmm……虽然时间可能能过但是你空间也存不下啊,所以我们要舍弃这个想法。

    我们有这样的式子:

    于是我们可以把后面的式子转换成这个,那么就变成了:

    phi的前缀和可以杜教筛做,k^2也是分块求和。

    具体的杜教筛式子可以看:http://blog.csdn.net/samjia2000/article/details/70147436

    #include<cstdio>
    #include<queue>
    #include<map>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=4700050;
    ll su[N],phi[N],sum[N],n,p,inv2,inv6;
    bool he[N];
    ll maxn=4700000;
    map<ll,ll>mp;
    inline ll s2(ll x){x%=p;return x*(x+1)%p*inv2%p;}
    inline ll s3(ll x){x%=p;return x*(x+1)%p*(2*x+1)%p*inv6%p;}
    inline ll sqr(ll x){x%=p;return x*x%p;}
    ll pow(ll x,ll y){
        ll res=1;
        while(y){
        if(y&1)res=res*x%p;
        x=x*x%p;
        y>>=1;
        }
        return res;
    }
    void Euler(int n){
        int tot=0;
        phi[1]=1;he[1]=1;
        for(int i=2;i<=n;i++){
        if(!he[i]){
            su[++tot]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=tot;j++){
            if(i*su[j]>n)break;
            he[i*su[j]]=1;
            if(i%su[j]==0){
            phi[i*su[j]]=phi[i]*su[j]%p;
            break;
            }
            else phi[i*su[j]]=phi[i]*phi[su[j]]%p;
        }
        }
        for(int i=1;i<=n;i++){
        phi[i]=(phi[i-1]+phi[i]*sqr(i)%p)%p;
        }
        return;
    }
    ll f(ll x){
        if(x<=maxn)return phi[x];
        if(mp[x])return mp[x];
        ll res=sqr(s2(x));
        for(ll i=2,j;i<=x;i=j+1){
        j=x/(x/i);
        res-=f(x/i)*(s3(j)-s3(i-1))%p;
        res%=p;
        }
        return mp[x]=(res+p)%p;
        
    }
    int main(){
        scanf("%lld%lld",&p,&n);
        inv2=pow(2,p-2);inv6=pow(6,p-2);
        maxn=min(maxn,n);
        Euler(maxn);
        ll ans=0;
        for(ll i=1,j;i<=n;i=j+1){
        j=n/(n/i);
        ans+=(f(j)-f(i-1))%p*sqr(s2(n/i))%p;
        ans%=p;
        }
        printf("%lld
    ",(ans+p)%p);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    Reaper自定义模板
    c#3.0 特性
    C#中下载文件出现410错误。
    使用Create task with ContentType创建任务的时候,必须先在task list中加上该ContentType
    tsmmc.msc 远程桌面
    工作流的ReplicatorActivity
    关于Windows2003的远程桌面链接数量。
    【手绘】A old painting ,drawed in middle school ,grade 8
    【Notepad++】Notepad ++ plugin Compare
    【资讯】Fight for this goal ,and better than this~
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8611961.html
Copyright © 2011-2022 走看看