f(i)=i∗[∑d|n10d∗μ(id)] f ( i ) = i ∗ [ ∑ d | n 10 d ∗ μ ( i d ) ]
求 ∑ni=1f(i) ∑ i = 1 n f ( i )
n n <= 1010 10 10
首先显然有
首先设 g(i) g ( i ) = ∑ij=1j∗10j ∑ j = 1 i j ∗ 10 j ,这个挺容易求,像求等比数列一样裂项求即可,求得
对答案式子分块求,现在只需要求 w(i)=∑ij=1μ(j)∗j w ( i ) = ∑ j = 1 i μ ( j ) ∗ j
考虑到有 w∗ID=[n=1] w ∗ I D = [ n = 1 ] ,于是可以用杜教筛求解,得
接下来只需预处理出前 n23 n 2 3 的 μ(i)∗i μ ( i ) ∗ i 即可。
#include
#include
#include
#include
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll K=52e5,N=521e4,U=2e5,mo=1e9+7;
int ss[K],oo;
bool bz[N];
int mu[N];
ll qz[N],keep[U],n9,n;
inline ll ksm(ll o,ll t)
{
ll y=1;
for(;t;t>>=1,o=o*o%mo)
if(t&1)y=y*o%mo;
return y;
}
inline ll op(ll t)
{return ((t*ksm(10,t+1)-(ksm(10,t+1)-1)*n9)%mo+mo+1)*n9%mo;}
inline ll ext(ll l,ll r)
{
ll o1=l+r,o2=r-l+1;
if(!(o1&1))o1>>=1;else o2>>=1;
return (o1%mo)*(o2%mo)%mo;
}
ll S(ll p)
{
if(p<=K)return qz[p];
else if(keep[n/p]!=-1)return keep[n/p];
ll l=2,r,lj=0;
while(l<=p){
r=p/(p/l); ll o=p/l;
lj=(lj+ext(l,r)*S(o))%mo;
l=r+1;
}
keep[n/p]=(1-lj+mo)%mo; return keep[n/p];
}
int main()
{
n9=ksm(9,mo-2);
fo(i,2,K){
if(!bz[i])ss[++oo]=i,mu[i]=-1;
fo(j,1,oo)if(ss[j]*i<=K){
bz[ss[j]*i]=true;
mu[ss[j]*i]=-mu[i];
if(i%ss[j]==0){
mu[ss[j]*i]=0;
break;
}
}else break;
}
mu[1]=1;
fo(i,1,U-2)keep[i]=-1;
fo(i,1,K)qz[i]=(qz[i-1]+mu[i]*(i%mo)+mo)%mo;
freopen("psy.in","r",stdin);
freopen("psy.out","w",stdout);
cin>>n;
ll l=1,r,ans=0;
while(l<=n){
r=n/(n/l);
ans=(ans+(S(r)-S(l-1)+mo)*op(n/l))%mo;
l=r+1;
}
cout<