[题目链接]

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. Android 一个强大的图片选择器

    看看下面的图片选择器,感觉很不错 http://www.jcodecraeer.com/a/anzhuokaifa/2017/0122/7083.html 看看下面的图片选择器,支持视频等 http: ...

  2. iPhone缓存网络数据

    本文转载至 http://blog.csdn.net/wwang196988/article/details/7542918   在iPhone应用程序中,我们经常要用去网络下载一些文件,比如xml, ...

  3. 白昼夢 / Daydream(模拟)

    C - 白昼夢 / Daydream Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement You ...

  4. 【译】常见 Java 异常解释(恶搞版)

    常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎o(╯□╰)o) java.lang ArithmeticException 你正在试图使用电脑解决一个自己解决不了的数学问题 ...

  5. 批处理设置IP地址

    echo offecho 修改[本地连接]IP......netsh interface IP set address "本地连接" static 138.8.8.111 255. ...

  6. linux后台开发必备技能

    一.linux和os: 1.命令:netstat tcpdump ipcs ipcrm  这四个命令的熟练掌握程度基本上能体现实际开发和调试程序的经验 2.cpu 内存 硬盘 等等与系统性能调试相关的 ...

  7. python 的for else语句

    for中间不是break出来的,是正常循环完跳出循环的会执行else内的语句 while else语句也是如此 这个以前的常见语言没有,特此记录

  8. 模仿jquery框架源码 -成熟---选择器

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  9. JS实现下拉列表的二级联动

    这个是简单也是最基本的下拉框联动的示例,这个示例主要针对那些只有二级联动,且第一级是固定的选项,第二级的内容也比较简单,不刷新的联动,动态的联动需要检索数据库,这个对不需要更新的二级联动比较实用.这里 ...

  10. jquery获取表单元素与回显

    一.获取哦表单元素 dcoument表单文本对象的集合 all[] 对所有html元素的访问 forms 返回对文档中所有form对象的引用 forms[1] 对所有form对象引用 <scri ...