显然,符合条件的数必须满足任何长度的后缀字典序必须严格大于全串。
假设一个串
T
T
可以由几个相同的串拼接而成,我们称
T
T
为循环串。显然所有循环串都是不满足条件的。
那么对于非循环串,那么其所有循环表示(就是切下一个前缀拼在后面)都是互不相同的。给出一个结论:一个合法串和一个环的最小循环表示串一一对应。
先证明一个合法串一定是最小循环表示串。(以下表示长度为
x
x
的前缀,表示长度为
x
x
的后缀)假设合法串不是最小循环表示串,那么设从第位开始,即
Sn−i+Pi(i≠0)
S
n
−
i
+
P
i
(
i
≠
0
)
是最小循环表示串,那么我们可以得到
Sn−i<Pn−i
S
n
−
i
<
P
n
−
i
(矛盾)或者
Sn−i=Pn−i
S
n
−
i
=
P
n
−
i
并且
Si<Pi
S
i
<
P
i
(也矛盾),于是得证。
再证明一个最小循环表示串一定是合法的。假设其不合法,那么必然存在一个
Si<Pi
S
i
<
P
i
(矛盾)或者
Si=Pi
S
i
=
P
i
并且把
Pn−i
P
n
−
i
拼到后面能得到
Pn−i>Si
P
n
−
i
>
S
i
(也矛盾),得证。
那么我们设
Fn
F
n
表示长度为
n
n
的合法串的个数,显然有:
其中 ∑d|ndFd ∑ d | n d F d 是减去循环串, 1n 1 n 是因为 n n 种循环表示中只有种合法。我们设 Gi=Fi⋅n2 G i = F i ⋅ n 2 ,问题要求的就是 ∑ni=1Gi ∑ i = 1 n G i ,那么:
前一个和式是一个等比数列乘等差数列,用错位相减直接求,后一个和式换成枚举 k=id k = i d ,得到
直接杜教筛即可。
代码:
include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int mod=1000000007;
const int R=100000;
const int T=3000000;
ll n,i9,i2;
int mg[R+5],g[T+5];
ll ksm(ll a,ll b)
{
ll r=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1) r=r*a%mod;
return r;
}
ll solve(ll x)
{
ll m=n/x,pp,ans;
if(m<T) return g[m];x=n/m;
if(x<R&&mg[x]>=0) return mg[x];
pp=ksm(10,m+1);
ans=(pp*(m-i9+mod)+i9+1)%mod*i9%mod;
for(ll l=2,r;l<=m;l=r+1)
{
r=m/(m/l);
ll s=((l+r)%mod)*((r-l+1)%mod)%mod*i2%mod;
ans=(ans-s*solve(x*l)%mod+mod)%mod;
}
if(x<R) mg[x]=ans;
return ans;
}
int main()
{
scanf("%lld",&n);
memset(mg,-1,sizeof(mg));
i9=ksm(9,mod-2);
i2=ksm(2,mod-2);
g[1]=10;
for(int i=2;i<=T;i++)
g[i]=10ll*g[i-1]%mod;
for(int i=1;i<=T;i++)
{
for(int j=(i<<1);j<=T;j+=i)
g[j]=(g[j]+mod-g[i])%mod;
g[i]=((ll)g[i]*i+g[i-1])%mod;
}
printf("%lld",solve(1));
return 0;
}