题解 [校内测试]图森破

题意

f ( n ) f(n) f(n) 为满足以下条件的字符串个数:

  1. 串长为 S S S,字符集为 [ 0 , 9 ] [0,9] [0,9]
  2. s u f i suf_i sufi 为第 i i i 个字符对应的后缀在最后补 0 0 0 补成长度为 n n n 得到的串,则 ∀ i ∈ [ 2 , n ] , s u f i > s u f 1 \forall i\in [2,n], suf_i>suf_1 i[2,n],sufi>suf1

试求 ∑ i = 1 n i 2 f ( i ) \sum_{i=1}^n i^2f(i) i=1ni2f(i) 258280327 258280327 258280327 得到的值。

组合

试求 f ( n ) f(n) f(n)

首先考虑长度为 n n n 的答案是什么。

首先所有循环节小于 n n n 的串是不合法的,这十分显然。

然后对于一个不具有循环节的串,我们可以转它( newS i % n + 1 ← S i \text{newS}_{i\%n +1}\leftarrow S_i newSi%n+1Si),可以转出 n n n 个互不相同的串。下面我们证明这 n n n 个串中有且仅有一个是合法的。

  1. n n n 个串中至少有一个是合法的:

考虑设 S S S n n n 个串中字典序最小的串,若它不合法,则存在一个后缀 B < S B< S B<S。由于 S S S 是字典序最小的,因此 B B B 的长度不超过 ⌊ n 2 ⌋ \lfloor \frac{n}{2}\rfloor 2n


由于 S S S 是字典序最小的,因此如果设 S S S 去掉 B B B A A A,则 B B B A A A 的前缀。

然后考虑转到 B B B 的字符串。

由于 S S S 是字典序最小的,因此对应字符存在如下关系:


在这里插入图片描述
此时红色后缀循环移位后得到

  1. n n n 个串中至多有一个是合法的:

假设有两个串合法,设为 S 1 , S 2 S_1,S_2 S1,S2,考虑 S 2 S_2 S2 S 2 S_2 S2 S 1 S_1 S1 中的位置的后缀是 F 2 F_2 F2,另一个是 F 1 F_1 F1,知 S 2 ≥ F 2 , S 1 ≥ F 1 S_2\ge F_2,S_1\ge F_1 S2F2,S1F1(补 0),而 S 2 < F 1 , S 1 < F 2 S_2< F_1,S_1< F_2 S2<F1,S1<F2 (定义),故 S 2 ≥ F 2 > S 1 ≥ F 1 S_2\ge F_2>S_1\ge F_1 S2F2>S1F1,与 S 2 < F 1 S_2< F_1 S2<F1 矛盾!

因此我们只需要算循环节等于 n n n 的串的个数,设为 g ( n ) g(n) g(n)

事实上这非常好算啊!易知 ∑ d ∣ n g ( d ) = 1 0 n \sum_{d|n} g(d)=10^n dng(d)=10n,所以 g ( n ) = ∑ d ∣ n 1 0 n d × μ ( d ) g(n)=\sum_{d|n} 10^{\frac{n}{d}}\times \mu(d) g(n)=dn10dn×μ(d) (莫比乌斯反演)!

f ( n ) = 1 n ∑ d ∣ n 1 0 n d × μ ( d ) f(n)=\frac{1}{n}\sum_{d|n} 10^{\frac{n}{d}}\times \mu(d) f(n)=n1dn10dn×μ(d)

数论

∑ n = 1 N n ∑ d ∣ n μ ( n d ) 1 0 d = ∑ d = 1 N d 1 0 d ∑ n = 1 N / d n μ ( n ) \begin{aligned} & \sum_{n=1}^N n \sum_{d|n} \mu(\frac{n}{d})10^{d} \\ &= \sum_{d=1}^N d10^d \sum_{n=1}^{N/d} n\mu(n) \end{aligned} n=1Nndnμ(dn)10d=d=1Nd10dn=1N/dnμ(n)

注意到这是杜教筛简单题,因此 Θ ( n 2 / 3 log ⁡ n ) \Theta(n^{2/3}\log n) Θ(n2/3logn) 求解。(可以 Θ ( n 2 / 3 ) \Theta(n^{2/3}) Θ(n2/3),只需要把 map 和算 sum(i10i) 换掉,前者可以只记忆化 i 而不是 N/i,后者可以分块预处理来 O(1) 算 10^n)

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int NN = 5000000;
const int MOD = 258280327;
int mu[NN + 5], P[NN + 5], pl;
ll sum[NN + 5], ans, N;
bool np[NN + 5];
map<ll, ll> M;

ll power(ll a, ll b, ll p = MOD) {
	ll ret = 1; a %= p;
	for (; b; a = a * a % p, b >>= 1) if (b & 1) ret = ret * a % p;
	return ret;
}

const ll inv2 = power(2, MOD - 2), inv9 = power(9, MOD - 2);

ll getS(ll n) {
	if (n <= NN) return sum[n];
	if (M.find(n) != M.end()) return M[n];
	ll s = 1;
	for (ll i = 2, j; i <= n; i = j + 1) {
		j = n / (n / i);
		s = (s - getS(n / i) * (i + j) % MOD * (j - i + 1) % MOD * inv2) % MOD;
	} M[n] = s; return s;
}

inline ll S(ll n) {
	ll pw = power(10, n + 1); n %= MOD;
	return (pw * n - (pw - 10) * inv9) % MOD * inv9 % MOD;
}
int main() {
	scanf("%lld", &N), mu[1] = 1;
	for (int i = 2; i <= NN; ++i) {
		if (!np[i]) P[++pl] = i, mu[i] = -1;
		for (int j = 1; j <= pl && i * P[j] <= NN; ++j) {
			np[i * P[j]] = 1;
			if (i % P[j]) mu[i * P[j]] = mu[i] * mu[P[j]];
			else { mu[i * P[j]] = 0; break; }
		}
	}
	for (int i = 1; i <= NN; ++i) sum[i] = (sum[i - 1] + i * mu[i]) % MOD;
	getS(N);
	for (ll i = 1, j; i <= N; i = j + 1) {
		 j = N / (N / i);
		 ans = (ans + getS(N / i) * (S(j) - S(i - 1))) % MOD;
	}
	printf("%lld\n", (ans + MOD) % MOD);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值