[杜教筛+莫比乌斯反演] HDU5608: function

题意这里写图片描述

题解

我们设 g(i)=i23i+2 ,题目告诉我们的就是 g=f1 。然后就可以根据杜教筛的思路搞了:

i=1ng(i)=i=1nd|if(d)=i=1ndnif(d)=i=1nS(ni)

S(n)=i=1ng(i)i=2nS(ni)

如何不预处理前面一部分的话 O(n34) 可能会T掉,所以先要求一段,怎么求呢?
反演一下, g=f1 f(n)=(gμ)(n)=d|ng(d)μ(nd) ,然后 nlnn 暴力算就好了。

#include<cstdio> 
#include<cstring>
#include<algorithm>
#include<tr1/unordered_map>  
using namespace std;  
using namespace std::tr1;
typedef long long LL;
const int N=1000000, maxn=N+5;
const LL MOD=1000000007, inv=(MOD+1)/3;  
int Q,p[maxn],mu[maxn];
bool vis[maxn];
int sum[maxn];

void Pre(){
    memset(vis,1,sizeof(vis));
    mu[1]=1;
    for(int i=2;i<=N;i++){
        if(vis[i]) p[++p[0]]=i, mu[i]=-1;
        for(int j=1;j<=p[0]&&p[j]*i<=N;j++){
            vis[p[j]*i]=false;
            if(i%p[j]==0){ mu[p[j]*i]=0; break; }
            mu[p[j]*i]=-mu[i];
        }
    }
    for(int i=1;i<=N;i++)
     for(int j=1;(LL)i*j<=N;j++) (sum[i*j]+=((LL)i-1)*(i-2)*mu[j]%MOD)%=MOD;
    for(int i=1;i<=N;i++) (sum[i]+=sum[i-1])%=MOD;

}
unordered_map<int, int> lst;
int Sum(int n){
    if(n<=N) return (sum[n]+MOD)%MOD; 
    if(lst.find(n)!=lst.end()) return lst[n];
    int res=((LL)n)*(n-1)%MOD*(n-2)%MOD*inv%MOD;
    for(LL i=2,nxt;i<=n;i=nxt+1){
        nxt=n/(n/i); (res+=MOD-(nxt-i+1)*Sum(n/i)%MOD)%=MOD;
    }
    return lst[n]=(res+MOD)%MOD;
}

int main(){
    freopen("hdu5608.in","r",stdin);
    freopen("hdu5608.out","w",stdout);
    Pre();  
    scanf("%d",&Q);  
    while (Q--){  
        int n; scanf("%d",&n);  
        printf("%d\n",Sum(n));  
    } 
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值