您的位置:首页 > 其它

【bzoj4176】Lucas的数论

2017-12-28 21:07 211 查看
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
,ans;
int n,p
,tot;
map<int,ll>mp_miu;
bool flag
;
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
;
if (mp_miu
) return mp_miu
;
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
=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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: