题目
Description
Input
从文件 divisor.in 中读入数据。
只有一行,输入一个整数n 。
Output
输出到文件 divisor.out 中。
输出一行,一个整数,表示式子的结果。由于三叶只需要你的验证而不是给出答案,所以你只需要输出答案(式子的值)对 10^+7取模的值。
Sample Input
Sample Input1
3
Sample Input2
985
Sample Output
Sample Output1
15
Sample Output2
349880989
Data Constraint
思路
首先对式子进行反演
发现后面那一部分可以整除划分,前面那一部分可以杜教筛。
注意,要预处理多一些否则会T
代码
#include<cstdio>
#define P(x,y) x=(x+y)%mod
#define ll long long
using namespace std;
const int A=1e7,mod=1e9+7,M=1e6+3;
ll n,x,ans,mu[A+9],v[34567890],rf[M],rg[M];
int tot=2*A,ps,p[A+9],f[M],g[M];
bool b[M*10];
ll G(ll n)
{
if(!n) return 0;
if(n<=A) return v[A+n];
int x=n%M; while(rg[x]&&rg[x]!=n)x=(x+1)%M;
if(rg[x]==n) return v[g[x]];
int _=g[x]=++tot; rg[x]=n;
for(ll i=2,j; i<=n; i=j+1)
{
j=n/(n/i);
P(v[_],(i+j)%mod*(j-i+1)%mod*(mod+1>>1)%mod*G(n/i));
}
return v[_]=(1-v[_]+mod)%mod;
}
ll F(ll n)
{
if(!n) return 0;
if(n<=A) return v[n];
int x=n%M; while(rf[x]&&rf[x]!=n)x=(x+1)%M;
if(rf[x]==n) return v[f[x]];
int _=f[x]=++tot; rf[x]=n;
for(ll i=1,j; i<=n; i=j+1)
{
j=n/(n/i);
P(v[_],(j-i+1)%mod*G(n/i));
}
return v[_];
}
int main()
{
freopen("divisor.in","r",stdin); freopen("divisor.out","w",stdout);
mu[1]=1,v[1]=1,v[A+1]=1;
for(int i=2; i<=A; i++)
{
if(!b[i]) mu[p[++ps]=i]=mod-1,v[i]=mod-i+1;
v[A+i]=(v[A+i-1]+i*mu[i])%mod;
for(int j=1;j<=ps&&(j==1||i%x)&&i*(x=p[j])<=A;j++)
{
b[i*x]=1,mu[i*x]=i%x?(mod-mu[i])%mod:0;
v[i*x]=i%x?v[i]*v[x]%mod:v[i];
}
}
for(int i=2; i<=A; i++) P(v[i],v[i-1]);
scanf("%lld",&n);
for(ll i=1,j,k; i<=n; i=j+1)
{
j=n/(k=n/i); k%=mod;
P(ans,k*(k+1)/2%mod*k%mod*(F(j)-F(i-1)+mod));
}
printf("%lld",ans);
}