【bzoj4176】Lucas的数论

Description

去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了。

在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数。他现在长大了,题目也变难了。
求如下表达式的值:
这里写图片描述
其中 表示ij的约数个数。
他发现答案有点大,只需要输出模1000000007的值。
Input

第一行一个整数n。

Output

一行一个整数ans,表示答案模1000000007的值。

Sample Input

2
Sample Output

8
HINT

对于100%的数据n <= 10^9。

题解
Orz YZH
http://blog.csdn.net/yzhyzhyzh3/article/details/78751440

#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define mod 1000000007
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int N = 2500005;
ll miu[N],ans;
int n,p[N],tot;
map<int,ll>mp_miu;
bool flag[N];
void prepration()
{
    miu[1]=1LL;
    for (int i=2;i<N;i++)
    {
        if (!flag[i]){p[++tot]=i;miu[i]=-1;}
        for (int j=1;j<=tot&&p[j]*i<N;j++)
        {
            flag[i*p[j]]=1;
            if (i%p[j]==0){miu[i*p[j]]=0;break;}
            miu[i*p[j]]=-miu[i];
        }
    }
    for (int i=2;i<N;i++) miu[i]+=miu[i-1];
}
inline ll calmiu(int n)
{
    if (n<N) return miu[n];
    if (mp_miu[n]) return mp_miu[n];
    ll ans=1LL,pos=0;
    for (ll i=2;i<=n;i=pos+1)
    {
        pos=n/(n/i);
        ans-=calmiu(n/i)*(pos-i+1);
    }
    mp_miu[n]=ans;
    return ans;
}
ll cal(int n)
{
    int pos;ll ans=0;
    for (int i=1;i<=n;i=pos+1)
    {
        pos=n/(n/i);
        ans=(ans+(ll)(n/i)*(pos-i+1)%mod)%mod;
    }
    return ans;
}
ll sqr(ll n)
{
    return n*n%mod;
}
int main()
{
    n=read();int pos=0;prepration();
    for (int i=1;i<=n;i=pos+1)
    {
        pos=n/(n/i);
        ans=(ans+(ll)(calmiu(pos)-calmiu(i-1)+mod)%mod*sqr((ll)cal(n/i))%mod)%mod;
    }
    cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值