题解 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}) \]

image
然后前面那部分可以杜教筛
看看后面这个东西怎么做

  • 关于「等差数列乘等比数列」的解法:
    image
    image
点击查看代码
#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;
}
posted @ 2022-01-03 21:04  Administrator-09  阅读(0)  评论(0编辑  收藏  举报