pta天梯赛L3部分题解
可怜的简单题
题意
我们有一个随机过程:
- 初始数列 \(A\) 为空。
- 从区间 \([1, n]\) 中均匀随机选择一个整数 \(i\) 加入 \(A\)。
- 如果存在大于 1 的正整数 \(w\) 使得 \(A\) 中所有元素都是 \(w\) 的倍数(即 \(\gcd(A) > 1\)),则返回步骤 2 继续添加元素。
- 否则(\(\gcd(A) = 1\)),停止并返回 \(A\)。
求停止时数列 \(A\) 的期望长度,结果对质数 \(p\) 取模(\(p > n\))。
思路
设 \(f(d,x)\) 为序列的前 \(x\) 位 \(gcd\) 被 \(d\) 整除的概率。
设 \(g(d,x)\) 为序列的前 \(x\) 位 \(gcd\) 为 \(d\) 的概率。
不难得出 \(f(d,x)=(\frac{\lfloor \frac{n}{d}\rfloor}{n})^x.\)
\(\displaystyle f(d,x)=\sum_{d|k}g(k,x).\)
\(\iff\displaystyle g(d,x)=\sum_{d|k}\mu(\frac{k}{d})\cdot f(k,x).\)
\(\displaystyle g(1,x)=\sum^{n}_{k=1}\mu(k)\cdot f(k,x)=\sum^{n}_{k=1}\mu(k)\cdot(\frac{\lfloor \frac{n}{k}\rfloor}{n})^x.\)
那序列长度大于 \(x\) 的概率为 \(\displaystyle P(x)=1-g(1,x)=1-\sum^{n}_{k=1}\mu(k)\cdot(\frac{\lfloor \frac{n}{k}\rfloor}{n})^x\)
\(\displaystyle =-\sum^{n}_{k=2}\mu(k)\cdot(\frac{\lfloor \frac{n}{k}\rfloor}{n})^x\)
则序列的期望长度为
\(\displaystyle E=\sum^{\infty}_{x=0}P(x)=1-\sum^{\infty}_{x=1}\sum^{n}_{k=2}\mu(k)\cdot(\frac{\lfloor \frac{n}{k}\rfloor}{n})^x\)
\(\displaystyle =1-\sum^{n}_{k=2}\mu(k)\sum^{\infty}_{x=1}(\frac{\lfloor \frac{n}{k}\rfloor}{n})^x=1 -\sum^{n}_{k=2}\mu(k)(\frac{\lfloor \frac{n}{k}\rfloor}{n-\lfloor \frac{n}{k}\rfloor})\)
用数论分块和杜教筛即可求解。
代码
点击查看代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define double long double
#define PII pair<int,int>
#define PIV pair<int,vector<int>>
#define PIII pair<int,PII>
#define LL __int128
const int N = 2e6 + 10, INF = 1e18;
int mod = 998244353;
const int M = 4e2 + 10;
const double eps = 1e-6;
LL qpow(LL x, int n) {
LL ans = 1;
while (n) {
if (n & 1) {
ans *= x;
ans %= mod;
}
x *= x;
x %= mod;
n >>= 1;
}
return ans;
}
int fac[N], inv[N];
void fact(int K) {
fac[0] = 1;
for (int i = 1; i <= K; ++i) fac[i] = fac[i - 1] * i % mod;
inv[K] = qpow(fac[K], mod - 2);
for (int i = K - 1; i >= 0; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
}
int C(int n, int k) {
if (k < 0 || k > n) return 0;
return fac[n] * inv[k] % mod * inv[n - k] % mod;
}
constexpr int MAXN = 5000010;
long long T, n, pri[MAXN], cur, mu[MAXN], sum_mu[MAXN];
bool vis[MAXN];
map<long long, long long> mp_mu;
long long S_mu(long long x) { // 求mu的前缀和
if (x < MAXN) return sum_mu[x];
if (mp_mu[x]) return mp_mu[x]; // 如果map中已有该大小的mu值,则可直接返回
long long ret = (long long)1;
for (long long i = 2, j; i <= x; i = j + 1) {
j = x / (x / i);
ret -= S_mu(x / i) * (j - i + 1);
}
return mp_mu[x] = ret; // 路径压缩,方便下次计算
}
long long S_phi(long long x) { // 求phi的前缀和
long long ret = (long long)0;
long long j;
for (long long i = 1; i <= x; i = j + 1) {
j = x / (x / i);
ret += (S_mu(j) - S_mu(i - 1)) * (x / i) * (x / i);
}
return (ret - 1) / 2 + 1;
}
void init(){
mu[1] = 1;
for (int i = 2; i < MAXN; i++) { // 线性筛预处理mu数组
if (!vis[i]) {
pri[++cur] = i;
mu[i] = -1;
}
for (int j = 1; j <= cur && i * pri[j] < MAXN; j++) {
vis[i * pri[j]] = true;
if (i % pri[j])
mu[i * pri[j]] = -mu[i];
else {
mu[i * pri[j]] = 0;
break;
}
}
}
for (int i = 1; i < MAXN; i++)
sum_mu[i] = sum_mu[i - 1] + mu[i]; // 求mu数组前缀和
}
int H(int n){
LL res=0;
int l=2,r;
while(l<=n){
r=n/(n/l);
res+=(S_mu(r)-S_mu(l-1)+mod)%mod*((LL)(n/l)*qpow((n-n/l),mod-2)%mod)%mod;
// cout<<l<<' '<<r<<' '<<(S_mu(r)-S_mu(l-1)+mod)%mod<<' '<<((n/l)/(n-n/l))%mod<<endl;
res%=mod;
l=r+1;
}
return res;
}
void solve() {
init();
int n, p;
cin>>n>>mod;
cout<<(mod+1-H(n))%mod<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号