题解 Simple
首先转化成一个能做的形式:
若一个数的循环节不为 \(n\) 则不可选
若一个数的循环节为 \(n\) 则仅有最小表示可选
然后考虑容斥出循环节为 \(n\) 的数的个数
令 \(g(n)\) 为循环节为 \(n\) 的约数的数的个数,\(f(n)\) 为循环节恰好为 \(n\) 的数的个数
有
\[g(n)=\sum\limits_{d\mid n}f(n)=10^n
\]
所以
\[f(n)=\sum\limits_{d\mid n}\mu(d)g(\frac{n}{d})
\]
然后前面那部分可以杜教筛
看看后面这个东西怎么做
- 关于「等差数列乘等比数列」的解法:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
ll n;
const ll mod=258280327;
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
namespace force{
ll ans;
bool check(int n, int t) {
int x=t, p=1;
for (int i=1; i<=n; ++i) p=p*10;
for (int i=1; i<n; ++i) {
t=t*10%p;
if (t<=x) return 0;
}
return 1;
}
void solve() {
int lim=10;
for (int i=1; i<=n; ++i,lim*=10) {
int cnt=0;
for (int j=0; j<lim; ++j)
if (check(i, j)) ++cnt;
ans=(ans+i*i%mod*cnt)%mod;
}
printf("%lld\n", ans);
exit(0);
}
}
namespace task{
bool npri[N];
int pri[N], pcnt, mu[N];
ll smu[N], inv[N], ans;
unordered_map<ll, ll> mp;
inline ll pre(ll n) {n%=mod; return n*(n+1)%mod*inv[2]%mod;}
inline ll f(ll n) {return ((n*inv[9]%mod-inv[81])*qpow(10, n+1)%mod+10*inv[81])%mod;}
ll qsum(ll n) {
if (n<N) return smu[n];
if (mp.find(n)!=mp.end()) return mp[n];
ll ans=1;
for (ll l=2,r; l<=n; l=r+1) {
r=n/(n/l);
ans=(ans-(pre(r)-pre(l-1))*qsum(n/l))%mod;
}
return mp[n]=ans;
}
void solve() {
mu[1]=inv[0]=inv[1]=1;
for (int i=2; i<=100; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<N; ++i) {
if (!npri[i]) pri[++pcnt]=i, mu[i]=-1;
for (int j=1,x; j<=pcnt&&i*pri[j]<N; ++j) {
npri[x=i*pri[j]]=1;
if (!(i%pri[j])) break;
else mu[x]=-mu[i];
}
}
for (int i=1; i<N; ++i) smu[i]=(smu[i-1]+mu[i]*i)%mod;
for (ll l=1,r; l<=n; l=r+1) {
r=n/(n/l);
ans=(ans+(qsum(r)-qsum(l-1))*f(n/l))%mod;
}
printf("%lld\n", (ans%mod+mod)%mod);
exit(0);
}
}
signed main()
{
n=read();
// force::solve();
task::solve();
return 0;
}