题解 | #简单的数学题#

简单的数学题

https://ac.nowcoder.com/acm/contest/16832/B

B题:简单的数学题
大概思路是杜教筛+莫比乌斯反演+枚举+整除分块优化+记忆化优化
图片说明
代码如下:

#include<iostream>
#include<string.h>
#include<unordered_map>

#define lint long long

#define mod 1000000007

#define pren 5000007
#define dnprime 5000007

using
        namespace
                    std;

bool isprime[pren];
lint prime[dnprime],nprime;
lint myu[pren],smyu[pren];

unordered_map<lint,lint> bsmyu;
unordered_map<lint,lint> preans,subpreans;

void prework(){
    memset(isprime,true,sizeof(isprime));
    memset(myu,0,sizeof(myu));
    nprime=0;
    myu[0]=0,myu[1]=1;

    for(lint i=2;i<pren;i++){
        if(isprime[i]){
            prime[nprime]=i;
            myu[i]=-1;
            nprime++;
        }
        for(lint j=0;j<nprime&&i*prime[j]<pren;j++){
            isprime[i*prime[j]]=false;
            if(i%prime[j]==0){
                myu[i*prime[j]]=0;
                break;
            }
            else{
                myu[i*prime[j]]=-myu[i];
            }
        }
    }

    smyu[0]=0;
    for(int i=1;i<pren;i++){
        smyu[i]=smyu[i-1]+myu[i];
    }

    return;
}

lint find_smyu(lint x){
    if(x<pren) return smyu[x];
    if(bsmyu[x]) return bsmyu[x];
    lint ans=1;
    for(lint l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans-=(r-l+1)*(find_smyu(x/l));
    }
    return bsmyu[x]=ans;
}

lint subcal(lint x){
    if(subpreans[x]) return subpreans[x];
    lint ans=x;
    for(lint l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans=(        ans
                +
                    (
                        ((r+l)*(r-l+1)/2)%mod
                        *
                        ((1+x/l)*(x/l)/2)%mod
                    )%mod
                +
                    (
                        (x*l)%mod
                        *
                        (x/(l-1)-x/l)
                    )%mod
                -
                    (
                        ((l*(l-1))/2)%mod
                        *
                        ((x/(l-1)-x/l)*(x/(l-1)+x/l+1))%mod

                    )%mod
            )%mod;
    }
    if(ans<0) ans+=mod;
    return subpreans[x]=ans;
}

lint cal(lint x){
    if(preans[x]) return preans[x];
    lint ans=0;
    for(lint l=1,r;l<=x;l=r+1){
        r=x/(x/l);
        ans=(ans+(find_smyu(r)-find_smyu(l-1))*(subcal(x/l)))%mod;
    }
    if(ans<0) ans+=mod;
    return preans[x]=ans;
}

signed main(){
    prework();
    int t;
    lint x;
    scanf("%d",&t);
    while(t--){
        scanf("%lld",&x);
        printf("%lld\n",cal(x));
    }
    return EOF+1;
}
全部评论

相关推荐

黑皮白袜臭脚体育生:简历统一按使用了什么技术实现了什么功能解决了什么问题或提升了什么性能指标来写会更好另外宣传下自己的开源仿b站微服务项目,GitHub已经410star,牛客上有完整文档教程,如果觉得有帮助的话可以点个小星星,蟹蟹
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务