CF1139D Steps to One 题解【莫比乌斯反演】【枚举】【DP】
反演套 DP 的好题(不用反演貌似也能做
Description
Vivek initially has an empty array \(a\) and some integer constant \(m\).
He performs the following algorithm:
- Select a random integer \(x\) uniformly in range from \(1\) to \(m\) and append it to the end of \(a\).
- Compute the greatest common divisor of integers in \(a\).
- In case it equals to \(1\), break
- Otherwise, return to step \(1\).
Find the expected length of \(a\). It can be shown that it can be represented as \(\frac PQ\) where \(P\) and \(Q\) are coprime integers and \(Q\neq 0\pmod{10^9+7}\). Print the value of \(P\cdot Q^{-1}\pmod{10^9+7}\).
Input
The first and only line contains a single integer \(m\)(\(1\le m\le 100000\)).
Output
Print a single integer — the expected length of the array \(a\) written as \(P\cdot Q^{-1}\pmod{10^9+7}\).
Examples
input
1
output
1
input
2
output
2
input
4
output
333333338
Note
In the first example, since Vivek can choose only integers from \(1\) to \(1\), he will have \(a=[1]\) after the first append operation, and after that quit the algorithm. Hence the length of \(a\) is always \(1\), so its expected value is \(1\) as well.
In the second example, Vivek each time will append either \(1\) or \(2\), so after finishing the algorithm he will end up having some number of \(2\)'s (possibly zero), and a single \(1\) in the end. The expected length of the list is \(1⋅\frac 12+2⋅\frac 1{2^2}+3⋅\frac 1{2^3}+\dots =2\).
题意
每一步在 \(1\sim m\) 中任选一个整数,问期望多少步后选出的数的最大公约数是 \(1\)。答案对 \(1\ 000\ 000\ 007\) 取模。
题解
因为每一步不会让已经选了的元素的 \(\gcd\) 和变大,因此认为是一个除自环外的有向无环图。对于自环我们很好处理,所以把它看成是一道期望 DP。
令 \(f[i]\) 表示当前的 \(\gcd\) 和为 \(i\),到 \(\gcd\) 和为 \(1\) 的状态的期望步数。因此把状态转移方程写出来
\]
这样的转移是 \(O(m^2)\) 的。但是我们发现,对于很多 \(j\),\(\gcd(i,j)\) 都是相等的,因此我们把这样的数整合到一起。
令 \(F(n)\) 表示 \(1\sim m\) 中有多少个数 \(i\) 满足 \(\gcd(x,i)=n\),其中视 \(x\) 为常数。
则计算 \(f[i]\) 就转化为了
\]
这样差不多就把枚举优化到了 \(\log n\) 的 \(d|i\)。
考虑怎么计算 \(F(n)\)
\]
令 \(G(n)=\sum_{n|d}F(d)\),则
G(n)&=\sum_{n|d}F(d)\\
&=\sum_{n|d}\sum_{i=1}^m[\gcd(x,i)=d]\\
&=\sum_{i=1}^m[n|\gcd(x,i)]\\
?&=\sum_{i=1}^{\left\lfloor\frac mn\right\rfloor}\left[1|\gcd\left(\frac xn,i\right)\right]
\end{aligned}
\]
实际上这样是有问题的,因为(在后面)无法保证 \(n|x\),此时 \(G(n)\) 就一定为 \(0\) 了。
我们再多化一步:
G(n)&=\sum_{i=1}^{\left\lfloor\frac mn\right\rfloor}\left[1|\gcd\left(\frac xn,i\right)\right][n|x]\\
&=\left\lfloor\frac mn\right\rfloor\cdot[n|x]
\end{aligned}
\]
根据 \(G(n)=\sum_{n|d}F(d)\),我们反演到 \(F\),得
F(n)&=\sum_{n|d}\mu\left(\frac dn\right)G(d)\\
&=\sum_{i=1}^{\left\lfloor\frac mn\right\rfloor}\mu(i)G(ni)\\
&=\sum_{i=1}^{\left\lfloor\frac mn\right\rfloor}\mu(i)\left\lfloor\frac{m}{ni}\right\rfloor[(ni)|x]
\end{aligned}
\]
我们发现后面的布尔表达式可以当作条件。原本的条件本来就是 \(\to +\infty\) 的,只不过超过了 \(\left\lfloor\frac mn\right\rfloor\) 没有意义。因此直接把条件换成 \([(ni)|x]\) 即可。又因为 \(n|x\) 在上面的枚举过程中是成立的,同时可以转化为 \(\left[i|\frac xn\right]\)。
\]
这样的一次枚举是 \(O\left(d\left(\frac xn\right)\right)\) 的,由于 \(1\sim m\) 的约数个数和均摊是 \(O(\log m)\) 的,其中最多的有 \(128\) 个约数,但是这样的数肯定不是很多,并且其中很多被枚举到的数都是质因数,迭代一下并不会造成很大的复杂度。
然后我们需要再把状态转移方程稍微转化一下,把 \(f[i]\) 移到左边
f[i]&=1+\frac{\sum_{d|i,d<i}f[d]\times F(d)+f[i]\times F(i)}n,x=i\\
\frac{n-F(i)}{n}\cdot f[i]&=1+\frac{\sum_{d|i,d<i}f[d]\times F(d)}n,x=i\\
f[i]&=\frac{n+\sum_{d|i,d<i}f[d]\times F(d)}{n-F(i)},x=i
\end{aligned}
\]
就得到了真正的转移方程。
时间复杂度 \(O(m\log^2 m)\)。
Code:
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define p 1000000007
using std::vector;
vector<int> v[100100];//约数用 vector 存一下,每次 √m 枚举不是很稳
ll qpow(ll x,ll y)
{
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%p;
x=x*x%p;
y>>=1;
}
return ans;
}
bool is[100100];
int pri[100100],mu[100100],cnt=0;
ll f[100100];
int n;
int calc(int x,int y)//1~n 中 gcd(x,i)=y 的数的个数
{
int g=x/y,ans=0;
for(int i=0;i<v[g].size();++i)
ans+=mu[v[g][i]]*(n/v[g][i]/y);
return ans;
}
int main()
{
scanf("%d",&n);
f[1]=1;
mu[1]=1;
for(int i=2;i<=n;++i)
{
if(!is[i])
{
pri[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*pri[j]<=n;++j)
{
is[i*pri[j]]=1;
if(i%pri[j])
mu[i*pri[j]]=-mu[i];
else
{
mu[i*pri[j]]=0;
break;
}
}
}
for(int i=1;i<=n;++i)
for(int j=i;j<=n;j+=i)
v[j].push_back(i);
ll ans=1,inv=qpow(n,p-2);
for(int i=2;i<=n;++i)
{
for(int j=0;j<v[i].size()-1;++j)
f[i]=(f[i]+calc(i,v[i][j])*f[v[i][j]]%p)%p;
f[i]=(f[i]*inv+1)%p;
ll g=n-calc(i,i);
f[i]=f[i]*n%p*qpow(g,p-2)%p;
ans=(ans+f[i])%p;
}
printf("%lld\n",ans*qpow(n,p-2)%p);
return 0;
}
CF1139D Steps to One 题解【莫比乌斯反演】【枚举】【DP】的更多相关文章
- CF1139D Steps to One (莫比乌斯反演 期望dp)
\[ f[1] = 0 \] \[ f[i] = 1 + \frac{1}{m} \sum_{j = 1} ^ n f[gcd(i, j)] \ \ \ \ \ \ (i != 1) \] 然后发现后 ...
- Problem b 莫比乌斯反演+枚举除法的取值
莫比乌斯反演+枚举除法的取值 第二种形式: f(n)表示gcd(x,y)=n的数量. F(n)表示gcd(x,y)是n的倍数的数量. /** 题目:Problem b 链接:https://vjudg ...
- 【51nod1678】lyk与gcd(莫比乌斯反演+枚举因数)
点此看题面 大致题意: 一个长度为\(n\)的数组,实现两种操作:单点修改,给定\(i\)求\(\sum_{j=1}^na_j[gcd(i,j)=1]\). 莫比乌斯反演 考虑推一推询问操作的式子: ...
- 【bzoj3529】[Sdoi2014]数表 莫比乌斯反演+离线+树状数组
题目描述 有一张n×m的数表,其第i行第j列(1 <= i <= n ,1 <= j <= m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. ...
- 【bzoj3561】DZY Loves Math VI 莫比乌斯反演
题目描述 给定正整数n,m.求 输入 一行两个整数n,m. 输出 一个整数,为答案模1000000007后的值. 样例输入 5 4 样例输出 424 题解 莫比乌斯反演 (为了方便,以下公式默认$ ...
- 【bzoj4407】于神之怒加强版 莫比乌斯反演+线性筛
题目描述 给下N,M,K.求 输入 输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意义如上式所示. 输出 如题 ...
- 【bzoj4816】[Sdoi2017]数字表格 莫比乌斯反演
题目描述 Doris刚刚学习了fibonacci数列.用f[i]表示数列的第i项,那么 f[0]=0 f[1]=1 f[n]=f[n-1]+f[n-2],n>=2 Doris用老师的超级计算机生 ...
- [Noi2010]能量采集 (莫比乌斯反演)
[Noi2010]能量采集 Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后, 栋栋再使用一个能量汇集机器把这些植物采集到的能 ...
- 【HDU1695】GCD(莫比乌斯反演)
[HDU1695]GCD(莫比乌斯反演) 题面 题目大意 求\(a<=x<=b,c<=y<=d\) 且\(gcd(x,y)=k\)的无序数对的个数 其中,你可以假定\(a=c= ...
随机推荐
- 解决root@localhost's password:localhost:permission denied,please try again
背景:在装完Hadoop及jdk之后,在执行start-all.sh的时候出现 root@localhost's password:localhost:permission denied,please ...
- iOS密码输入框的实现
[iOS密码输入框的实现] 就是一个UITextField,把属性 UITextField.secureTextEntry设置为Yes即可.此种UI效果为iOS默认效果.
- PMP项目管理笔记
项目管理三重制约:时间.成本.范围.结果:质量(结果质量和过程质量)四个层次:复杂事情简单化:分解简单事情量化:临界值量化的事情专业化:规律专业的事情模板化:框架模板 工作分日常运作和项目.日常运作为 ...
- 关于Safari浏览器使用的几点总结
声明:下载的是Safari英文版本,在Windows操作系统下使用. 一.Safari浏览器中的开发者调试工具隐藏得比较深,找了好久才找到的,方法:按一下键盘上的alt键,浏览器上方就会弹出一个开发者 ...
- sublime主题选择
Sublime Text是一个强大的令人难以置信的编辑器. 它不仅具有大量的功能,而且还有很多主题,让他看起来很漂亮. 我们以前整理过 2014年的最好的主题 ; 让我们看看最新的Sublime Te ...
- EBS SOA 修改Web Service参数
l 需求描述 当把PL/SQL声明Load到ISG,生成WSDL并部署完毕后,需要修改PL/SQL的包头声明部分.例如修改某个过程的参数类型,再重新Load,重新生成WSDL,重新部署.我们会发现PL ...
- [Erlang33]使用recon从网页查看Erlang运行状态
0.需求分析 Erlang最好的卖点之一就是提供了一个非常强大的shell来查看Node运行时的各种状态,可以进行各种各样的内部查看,在运行时调试和分析,热更新代码. 但是总有一些在生产环境下要慎 ...
- selenium + PhantomJS 爬取js页面
from selenium import webdriver import time _url="http://xxxxxxxx.com" driver = webdriver.P ...
- 启动hive命令时指定参数或自定义参数
启动hive命令时指定参数或自定义参数 在hive启动命令中指定一个参数 hive --hiveconf hive.job.submit.username=fuxin.zhao -e "se ...
- iOS 错误 undefined symbols for architecture i386
undefined symbols for architecture i386 这个错误困扰了我几个小时. 网上很多问这个问题的,回答基本上都是说在 target 里面去的 armv64 什么什么的. ...