[题目链接]

https://codeforces.com/contest/1139/problem/D

[算法]

考虑dp

设fi表示现在gcd为i , 期望多少次gcd变为1

显然 , fi = (1 / m) * sigma{ fgcd(i , j) } + 1

直接转移是O(N ^ 2logN)的 , 显然不能通过

考虑在转移时枚举gcd , 显然gcd只可能是i的约数 , 可以在dp前O(NlogN)预处理每个数的约数

于是问题转化为求一个形如 : [1 , m]中有多少个数与i的gcd为j的问题

这等价于求 : [1 , m / j]中有多少个数与(i / j)的gcd为1

容斥原理计算即可

时间复杂度 : O(NlogN)( 有较大的常数 )

[代码]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int P = 1e9 + ;
const int MAXP = 1e5 + ; #define rint register int int m , tot;
int f[MAXP] , prime[MAXP] , dp[MAXP];
vector< int > d[MAXP]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline int exp_mod(int a , int n)
{
int b = a , res = ;
while (n > )
{
if (n & ) res = 1LL * res * b % P;
b = 1LL * b * b % P;
n >>= ;
}
return res;
}
inline int calc(int N , int M)
{
vector< int > pr;
int tmp = N / M;
while (tmp != )
{
pr.push_back(f[tmp]);
tmp /= f[tmp];
}
int sz = unique(pr.begin() , pr.end()) - pr.begin();
int limit = m / M , res = ;
for (int i = ; i < ( << sz); ++i)
{
int sign = , val = ;
for (int j = ; j < sz; ++j)
{
if (i & ( << j))
{
sign *= -;
val *= pr[j];
}
}
res += 1LL * sign * (limit / val);
}
return res;
} int main()
{ read(m);
for (rint i = ; i <= m; ++i)
{
for (rint j = i; j <= m; j += i)
{
d[j].push_back(i);
}
}
for (rint i = ; i <= m; ++i)
{
if (!f[i])
{
prime[++tot] = i;
f[i] = i;
}
for (int j = ; j <= tot; ++j)
{
int tmp = i * prime[j];
if (tmp >= MAXP) break;
f[tmp] = prime[j];
if (prime[j] == f[i]) break;
}
}
dp[] = ;
for (rint i = ; i <= m; ++i)
{
int res = ;
for (unsigned j = ; j < d[i].size(); ++j)
{
int D = d[i][j];
if (D != i) res = (res + 1LL * calc(i , D) * dp[D] % P) % P;
}
res = 1LL * res * exp_mod(m , P - ) % P;
res = (res + ) % P;
int fm = m - calc(i , i);
res = 1LL * res * exp_mod(fm , P - ) % P * m % P;
dp[i] = res;
}
int ans = ;
for (rint i = ; i <= m; ++i) ans = (ans + 1LL * exp_mod(m , P - ) * dp[i] % P) % P;
printf("%d\n" , ans); return ; }

[Codeforces 1139D] Steps to One的更多相关文章

  1. codeforces#1139D. Steps to One (概率dp+莫比乌斯反演)

    题目链接: http://codeforces.com/contest/1139/problem/D 题意: 在$1$到$m$中选择一个数,加入到一个初始为空的序列中,当序列的$gcd$和为$1$时, ...

  2. Codeforces 1139D Steps to One dp

    Steps to One 啊, 我要死了, 这种垃圾题居然没写出来, 最后十分钟才发现错在哪. 不知道为什么我以为 对于一个数x , 除了它的因子和它的倍数都是和它互质的, 我脑子是抽了吗? 随便瞎d ...

  3. Codeforces.1139D.Steps to One(DP 莫比乌斯反演)

    题目链接 啊啊啊我在干什么啊.怎么这么颓一道题做这么久.. 又记错莫比乌斯反演式子了(╯‵□′)╯︵┻━┻ \(Description\) 给定\(n\).有一个初始为空的集合\(S\).令\(g\) ...

  4. Codeforces - 1139D - Steps to One (概率DP+莫比乌斯反演)

    蒟蒻数学渣呀,根本不会做. 解法是参考 https://blog.csdn.net/xs18952904/article/details/88785210 这位大佬的. 状态的设计和转移如上面博客一样 ...

  5. Codeforces 1139D(期望dp)

    题意是模拟一个循环,一开始有一个空序列,之后每次循环: 1.从1到m中随机选出一个数字添加进去,每个数字被选的概率相同. 2.检查这个序列的gcd是否为1,如果为1则停止,若否则重复1操作直至gcd为 ...

  6. Codeforces 1139D(推式子+dp)

    题目传送 推公式博客传送 推完式子就是去朴素地求就行了Orz const int maxn = 1e5 + 5; const int mod = 1e9 + 7; int m, mu[maxn], v ...

  7. 【Codeforces1139D_CF1139D】Steps to One (Mobius_DP)

    Problem: Codeforces 1139D Analysis: After ACing E, I gave up D and spent the left 30 minutes chattin ...

  8. Codeforces Round #321 (Div. 2) A. Kefa and First Steps 水题

    A. Kefa and First Steps Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/58 ...

  9. Codeforces #548 (Div2) - D.Steps to One(概率dp+数论)

    Problem   Codeforces #548 (Div2) - D.Steps to One Time Limit: 2000 mSec Problem Description Input Th ...

随机推荐

  1. commons-dbutils:1.6 ——java.sql.SQLException: 不支持的特性

    描述:使用jdbc创建连接后,使用commons-dbutils-1.6 数据库工具类,查询报错如下:java.sql.SQLException: 不支持的特性 Query: 经过测试跟踪在commo ...

  2. 列表按照字母排序检索SideBar

    项目中要求列表按照ABCD这种字母排序检索的功能,看了大神写的,瞬间崇拜了,接下来借大家参考参考了 首先是自定义view sidebar /** * @author J *一个自定义view 实现a- ...

  3. Miller-Rabin大素数测试模板

    根据费马小定理: 对于素数n,a(0<a<n),a^(n-1)=1(mod n) 如果对于一个<n的正整数a,a^(n-1)!=1(mod n),则n必不是素数. 然后就可以随机生成 ...

  4. 【BZOJ3563/3569】DZY Loves Chinese II 线性基神题

    [BZOJ3563/3569]DZY Loves Chinese II Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以 ...

  5. C#彻底解决Oledb连接Excel数据类型不统一的问题

    在使用Microsoft.Jet.OLEDB.4.0连接Excel,进行读取数据,相对使用传统的COM来读取数据,效率是很高的.但相对传统COM操作Excel来说,及存在数据类型转换的问题.因为使用O ...

  6. 我的Android进阶之旅------>Android视频录制小例子

    ============================首先看看官网上关于视频捕捉的介绍================================ Capturing videos Video ...

  7. python-安装 pip

    https://pip.pypa.io/en/stable/installing/ wget https://bootstrap.pypa.io/get-pip.py python get-pip.p ...

  8. spark0.9.0安装

    利用周末的时间安装学习了下最近很火的Spark0.9.0(江湖传言,要革hadoop命,O(∩_∩)O),并体验了该框架下的机器学习包MLlib(spark解决的一个重点就是高效的运行迭代算法),下面 ...

  9. SpringBoot学习笔记(4):添加自定义的过滤器

    SpringBoot:学习笔记(4)——添加自定义的过滤器 引入自定义过滤器 SpringBoot提供的前端控制器无法满足我们产品的需求时,我们需要添加自定义的过滤器. SpringBoot添加过滤器 ...

  10. c的详细学习(8)指针学习(二)

    (1)指针与二维数组 一个数组的名字代表该数组的的首地址,是地址常量(作为形式参数的数组名除外),这一规定对二维数组或更高维数组同样适用. 在c语言中定义的任何一个二维数组实际上都可以看做是一个一维数 ...