[题目链接]

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. Channel (Java NIO)

    [正文]netty源码死磕1.3:  Java NIO Channel 1. Java NIO Channel 1.1. Java NIO Channel的特点 和老的OIO相比,通道和NIO流(非阻 ...

  2. html/css背景图片自适应分辨率大小

    <style type='text/css'> .bgbox { position: absolute; left: 0; top: 0; width: 100%; overflow: h ...

  3. 20179209《Linux内核原理与分析》第十一周作业

    Nmap配合Metasploit进行端口扫描 1.Nmap扫描器基本使用 1.1简介 Nmap(Network Mapper)最早是Linux下的网络扫描嗅探器.其基本功能有三个: 探测一组主机是否在 ...

  4. CXF生成client注意事项

    1. 在使用wsdl2java命令生成client文件时在Service的Java文件中面出现super构造错误,这是因为jax-ws2.2规约与java6冲突  故须要减少jax-ws规约版本号. ...

  5. [转载]Java集合容器简介

    Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...

  6. did not find a matching property (tomcat+Eclipse 报错)

    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclips ...

  7. Nvidia NVENC 硬编码预研总结

    本篇博客记录NVENC硬编码的预研过程 github:  https://github.com/MarkRepo/NvencEncoder 步骤如下: (1)环境搭建 (2)demo编译,测试,ARG ...

  8. C#练习委托、事件、事件处理

    控制台应用程序效果: 代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  9. 【Flask】Sqlalchemy 增删该查操作

    ### sqlalchemy 增删改查操作, 通过session来进行操作. # coding:utf-8 # Author: liangjun. from sqlalchemy import cre ...

  10. 【Java】-BigInteger大数类的使用【超强Java大数模板 总结】

    Scanner cin = new Scanner(new BufferedInputStream(System.in)); 这样定义Scanner类的对象读入数据可能会快一些! 参考这个博客继续补充 ...