九条可怜去年出了一道题,导致一众参赛高手惨遭团灭。今年她出了一道简单题 —— 打算按照如下的方式生成一个随机的整数数列 A:
最开始,数列 A 为空。
可怜会从区间 [1,n] 中等概率随机一个整数 i 加入到数列 A 中。
如果不存在一个大于 1 的正整数 w,满足 A 中所有元素都是 w 的倍数,数组 A 将会作为随机生成的结果返回。否则,可怜将会返回第二步,继续增加 A 的长度。
现在,可怜告诉了你数列 n 的值,她希望你计算返回的数列 A 的期望长度。
输入格式:
输入一行两个整数 n,p (1≤n≤10^11,n<p≤10^12),p 是一个质数。
输出格式:
在一行中输出一个整数,表示答案对 p 取模的值。具体来说,假设答案的最简分数表示为 yx,你需要输出最小的非负整数 z 满足 y×z≡x mod p。
输入样例 1:
2 998244353
输出样例 1:
2
输入样例 2:
100000000 998244353
输出样例 2:
3056898
代码长度限制
16 KB
时间限制
10000 ms
内存限制
512 MB
由于本人能力、时间有限,仅给出最后表达式。
还有一些相乘有一些会爆long long 。。。。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e7+10;
const int M=2e7;
int n,mod;
int prime[N];
int mu[N];
bool vis[N];
int cnt;
unordered_map<int,int>sum_mu;
void init()
{
mu[1]=1;
for(int i=2; i<=M; i++)
{
if(vis[i]==0)
{
prime[++cnt]=i;
mu[i]=-1;
}
for(int j=1; j<=cnt&&i*prime[j]<=M; j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1; i<=M; i++)
{
mu[i]+=mu[i-1];
}
}
inline int f1(int x)
{
if(x<=M)
return mu[x];
if(sum_mu[x])
return sum_mu[x];
int ans=1;
for(int l=2,r; l<=x; l=r+1)
{
r=x/(x/l);
ans-=(r-l+1)*f1(x/l);
}
return sum_mu[x]=ans;
}
int qmul(int a,int b)
{
return (__int128)a*b%mod;
}
int qmi(int a,int b)
{
int res = 1;
while (b)
{
if (b & 1) res = qmul(res, a);
a = qmul(a, a);
b >>= 1;
}
return res;
}
void solve()
{
cin>>n>>mod;
int res = 1;
for (int l = 2, r; l <= n; l = r + 1)
{
r = n / (n / l);
int t = qmul(n / l, qmi(n - n / l, mod - 2));
res = (res - qmul(f1(r) - f1(l - 1), t) + mod) % mod;
}
cout << res << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
init();
int T;
T=1;
while(T--)
{
solve();
}
return 0;
}