51nod1220约数之和

51nod1220约数之和

Time Limit 3s Memory Limit 128KB
Description
σ(x) 表示x的约束和
ni=1nj=1σ(ij)
Input
一个数n(0 < n 109 )
Output
一个数答,对 109+7 取模。
Sample Input

1000

Sample Output

576513341

解题思路

莫比乌斯反演,杜教筛的各种技能
定义 [x] 的取值为1(x为真)否则为0

Ans=i=1nj=1nd|ijd

d|ij 能不能化为一个 d|j 呢,想到 d|ij 等同于 dgcd(i,d)|j

d|ij要满足 xy=d[x|i][y|j] ,x取 gcd(i,d) 能供给完 [x|i] 也就是说,这时 gcd(y,i)=1 当且仅当 y|j d|ij 成立,即 d|ijdgcd(i,d)|j

Ans=i=1nj=1nd=1ijd[dgcd(i,d)|j]=i=1nd=1indngcd(i,d)d=d=1ni=1nd=1in[gcd(i,d)=d]dndd      (dgcd(i,d))

gcd(i,d)=d ?
考虑化为 gcd(,)=1 很简单啊,用 idd 代替i,用 ddd 代替d

Ans=d=1nid=1nddd=1idn[gcd(id,dd)=1]dddddn

用i代替 id ,用d代替 dd
Ans=d=1ni=1ndd=1in[gcd(i,d)=1]ddnd=d=1ndi=1ndd=1n[gcd(i,d)=1]dnd=i=1nd=1nidd=1n[gcd(i,d)=1]dnd=i=1n12ni(ni+1)d=1n[gcd(i,d)=1]dnd

gcd(i,d)=1 怎么处理呢,想到 d|nμ(d)=[n=1] 那么
[gcd(i,d)=1]=k|gcd(i,d)μ(k)=k[k|i][k|d]μ(k)


Ans=i=1n12ni(ni+1)d=1ndndd=1n[d|i][d|d]μ(d)=d=1nμ(d)id=1ndiddnidddd=1nd12nddd(nddd+1)=d=1ndμ(d)i=1ndinidd=1nd12ndd(ndd+1)


f(x)=xμ(x)

g(x)=i=1xixi

h(x)=i=1x12xi(xi+1)

其实h和g是等价的

i=1x12xi(xi+1)=i=1xj=1xij(ij)=i=1xj=1xii=i=1xxii


Ans=d=1nf(d)g(nd)h(nd)=d=1ng(nd)2f(d)

我们想, nd 只有 2n

i<=n 时, i[1,n]
i>n 时, ni<n
ni 只有 2n
对于 i ,有j=max{x|nx=ni}=nni

所以,分块处理
ij[nni1+1,nni]nj=i
只需维护 s(x)=xi=1f(x) 即可, g(ni) 直接算
O(n)=niO(ni)=O(n34)

对于S(x)
d|nμ(d)=[n=1]
那么

1=i=1nid|iμ(d)=d=1ni=1niidμ(d)=d=1ni=1nidiμ(i)=d=1ndi=1nif(i)=d=1nds(nd)

s(n)=1d=2nds(nd)(d=1)

同样,分块处理 n4=n22 ,所以直接搜会有很多重复的项,哈希判重, O(n)=niO(ni)=o(n34)
预处理前 n23 项,复杂度可降到 O(n23)

总复杂度 O(n34)

#include<cstring>
#include<cstdio>
#include<cctype>
#define N 3001001
#define lim 43007
#define mo 1000000007
#define ny 500000004
using namespace std;
typedef long long ll;
ll n,s[N],sum[lim],hash[lim],mu[N],pr[N];
bool bz[N];
int get(ll x){
    int y=(int)(x%lim);
    while(hash[y] && hash[y]!=x)y++,y=y==lim?0:y;return y;
}
ll S(ll a){
    if(a<N)return s[a];
    int x=get(a);
    if(hash[x])return sum[x];
    hash[x]=a;ll ans=1;
    for(ll i=2,j;i<=a;i=j+1){
        j=a/(a/i);
        ans=(ans-(j+i)%mo*((j-i+1)%mo)%mo*ny%mo*S(a/i)%mo+mo)%mo;
    }sum[x]=ans;return ans;
}
ll g(ll a){
    ll ans=0;
    for(ll i=1,j;i<=a;i=j+1){
        j=a/(a/i);
        ans=(ans+a/i%mo*((i+j)%mo*((j-i+1)%mo)%mo*ny%mo))%mo;
    }return ans;
}
int main(){
    s[1]=mu[1]=1;
    for(ll i=2;i<N;i++){
        if(!bz[i])mu[pr[++pr[0]]=i]=-1;
        s[i]=(s[i-1]+mu[i]*i%mo+mo)%mo;
        for(int j=1;j<=pr[0] && i*pr[j]<N;j++){
            bz[i*pr[j]]=1;mu[i*pr[j]]=-mu[i];
            if(i%pr[j]==0){mu[i*pr[j]]=0;break;}
        }
    }
    scanf("%lld",&n);
    ll ans=0;
    for(ll i=1,j,las=0,now,t;i<=n;i=j+1,las=now){
        j=n/(n/i);now=S(j);t=g(n/i);
        ans=(ans+(now-las+mo)%mo*t%mo*t%mo)%mo;
    }
    printf("%lld",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值