更好的阅读体验

Description

给定一个数 \(n\),对它进行 \(k\) 次操作,每次将当前的数改为自己的因数,包括 \(1\) 和自己。写出变成所有因数的概率是相等的。求 \(k\) 次以后 \(n\) 期望会变成多少

Input

一行两个整数 \(n,k\)

Output

一行一个整数代表答案

Hint

\(1~\leq~n~\leq~10^{15}~,~1~\leq~k~\leq~10^4\)

Solution

Hello 2019!

我们考虑整个数字变化的树形图:

以 \(n~=~6~,~k~=~2\) 为例:

(恕我直言,这图是真的丑)

然后我们将这张图改一下,要求每个非叶节点都有 \(4\) 个孩子,如果孩子数不足,就让他们平分这四个。于是新的变化图如下:

(恕我直言,这图更丑了)

我们发现这张图上所有叶节点出现的概率都是等可能的,并且他们包含了所有的情况,所以求出这些数字的和再除以节点数就是期望值。

接着考虑由于一个数字的所有质因数都是独立的,同时每个质因子都可以画出类似的转移图,依据唯一分解定理,我们可以将质因子拆开,对于每个质因子求出他们期望变成多少,然后乘起来即为总期望。这里的质因子包括了质数 \(p\) 和它的指数 \(c\)。

接着考虑我们对质因子DP。一次对 \(p^c\) 的操作相当于将其变成 \(p^0,p^1,p^2,\dots p^c\) 中的任意一个。于是我们可以将一次操作转化成将指数 \(c\) 变成 \([1,c]\) 中任意一个数。我们规定任何一个节点都有 \(d(n)\) 个孩子, \(d(n)\) 为 \(n\) 的因数个数。则对于一个数值为 \(x\) 的节点,她有 \(\frac{1}{x + 1}\) 的概率变成 \(y~(0~\leq~y~\leq~x)\),那么它会占据 \(x\) 的 \(\frac{d(n)}{x + 1}\) 个孩子。

例如,对于 \(2^2\) 进行 \(2\) 次变化的指数图如下

我们认为粉色的位置每个数占据了 \(\frac{1}{2}\) 个儿子

于是我们考虑当我们进行了 \(i\) 次变化,第 \(w\) 个质因子在树形图上的第 \(i\) 层指数数值为 \(j\) 的节点个数,则显然有

\[f_{w,i,j}~=~\sum_{h = j}^{c_w}~f_{w,i - 1,h}~\times~\frac{d(n)}{h + 1}
\]

其中 \(c_j\) 为 \(n\) 的唯一分解式中对应项的指数。

于是我们枚举 \(n\) 的因数,求出他们出现的次数与他们值的乘积,除以最下面一层的节点个数即为答案

\[\begin{aligned}ans~& =~\frac{1}{d^k(n)}~\sum_{x \mid n}~Times_d~\times~x\\&=\frac{1}{d^k(n)}~\sum_{x \mid n}~d~\prod_{i = 1}^{d(n)}~f_{i,k,h}\end{aligned}
\]

其中 \(h\) 为 \(d\) 唯一分解式对应项的指数。

我们发现在 DP时,第 \(k\) 层每个位置都被乘了 \(d^k(n)\),于是可以和式子中的 \(\frac{1}{d^k(n)}\) 约掉,式子变为

\[f_{w,i,j}~=~\sum_{h = j}^{c_w}~f_{w,i - 1,h}~\times~\frac{1}{h + 1}
\]

\[\begin{aligned}ans~& =~\sum_{x \mid n}~Times_d~\times~x\\&=~\sum_{x \mid n}~d~\prod_{i = 1}^{d(n)}~f_{i,k,h}\end{aligned}
\]

看起来舒服多了。

考虑复杂度:我们枚举了 \(k\) 层,每层枚举了 \(n\) 的质因数个数次,这里的质因数不包括指数,但是包括重复的,例如 \(p^2\) 算作两个质因数。由于一个数 \(n\) 的质因数为 \(O(\log n)\),所以总状态复杂度为 \(O(k \log n)\)。在转移时,我们枚举的上界是 \(O(\log n)\),所以总复杂度为 \(O(k~\log^2 n)\)。发现转移的位置事实上转移了一个加权后缀和,于是我们再开一个数组维护这个后缀和即可做到 \(O(k \log n)\)。

注意到这样会爆空间,但是发现对于每个DP状态我们只需要第 \(k\) 层的情况,并且第一维互不影响,于是我们可以把第一维省掉,每次DP完一个质因子用另一个数组记录第 \(k\) 层的答案,即可做到空间复杂度 \(O(\log^2 n~+~k~\log n)\)。(其实动态开DP数组可以做到空间复杂度 \(O(k~\log n)\),但是没啥意义)

最后统计答案时直接爆搜因数即可。

Code

#include <cstdio>
#include <cstring>
#include <vector>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long typedef long long ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxt = 60;
const int maxm = 10010;
const int MOD = 1000000007; ll n, kk, ans;
ll frog[maxm][maxt], inv[maxt], gorf[maxt][maxt], sum[maxm][maxt];
std::vector<ll> d;
int cnt;
int c[maxt]; void Get_Inv(ci, ci);
void dfs(ci, ci);
int mpow(cl x, int); signed main() {
freopen("1.in", "r", stdin);
qr(n); qr(kk);
Get_Inv(59, MOD);
ll dn = n;d.push_back(0);
for (ll i = 2; (i * i) <= n; ++i) if(!(dn % i)) {
d.push_back(i); ++cnt;
while (!(dn % i)) {dn /= i; ++c[cnt];}
}
if (dn != 1) {++cnt; d.push_back(dn); c[cnt] = 1;}
for (rg int j = 1; j <= cnt; ++j) {
frog[0][c[j]] = sum[0][c[j]] = inv[c[j] + 1];
for (rg int i = 0; i < c[j]; ++i) frog[0][i] = 0, sum[0][i] = sum[0][c[j]];
for (rg int i = 1; i <= kk; ++i) {
rg int di = i - 1;
sum[i][c[j] + 1] = 0;
for (rg int k = c[j]; ~k; --k) {
frog[i][k] = sum[di][k];
sum[i][k] = (sum[i][k + 1] + frog[i][k] * inv[k + 1] % MOD) % MOD;
}
}
for (rg int k = 0; k <= c[j]; ++k) gorf[j][k] = frog[kk][k];
}
dfs(1, 1);
qw((ans + MOD) % MOD, '\n', true);
return 0;
} void Get_Inv(ci x, ci p) {
inv[1] = 1;
for (rg int i = 2; i <= x; ++i) inv[i] = - p / i * inv[p % i] % MOD;
} void dfs(ci cur, ci v) {
if (cur > cnt) {ans = (ans + v) % MOD; return;}
for (int i = 0; i <= c[cur]; ++i) dfs(cur + 1, 1ll * gorf[cur][i] * v % MOD * mpow(d[cur], i) % MOD);
} int mpow(cl x, int y) {
ll _ret = 1, _temp = x % MOD;
while (y) {
if (y & 1) _ret = _ret * _temp % MOD;
_temp = _temp * _temp % MOD;
y >>= 1;
}
return _ret;
}

【DP】【CF1097D】 Makoto and a Blackboard的更多相关文章

  1. T2980 LR棋盘【Dp+空间/时间优化】

    Online Judge:未知 Label:Dp+滚动+前缀和优化 题目描述 有一个长度为1*n的棋盘,有一些棋子在上面,标记为L和R. 每次操作可以把标记为L的棋子,向左移动一格,把标记为R的棋子, ...

  2. 【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】

    最开始想的暴力DP是把天数作为一个维度所以怎么都没有办法优化,矩阵快速幂也是$O(n^3)$会爆炸. 但是没有想到另一个转移方程:定义$f[i][j]$表示每天都有值的$i$天,共消费出总值$j$的方 ...

  3. 【DP+树状数组】BZOJ1264-[AHOI2006]基因匹配Match

    [题目大意] 给定n个数和两个长度为n*5的序列,两个序列中的数均有1..n组成,且1..n中每个数恰好出现5次,求两个序列的LCS. [思路] 预处理每个数字在a[i]中出现的五个位置.f[i]示以 ...

  4. BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】

    题目 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难看 ...

  5. 【DP|多重背包可行性】POJ-1014 Dividing

    Dividing Time Limit: 1000MS Memory Limit: 10000K Description Marsha and Bill own a collection of mar ...

  6. COGS 862. 二进制数01串【dp+经典二分+字符串】

    862. 二进制数01串 ★   输入文件:kimbits.in   输出文件:kimbits.out   简单对比 时间限制:1 s   内存限制:128 MB USACO/kimbits(译 by ...

  7. CodeForces - 597C Subsequences 【DP + 树状数组】

    题目链接 http://codeforces.com/problemset/problem/597/C 题意 给出一个n 一个 k 求 n 个数中 长度为k的上升子序列 有多少个 思路 刚开始就是想用 ...

  8. hihocoder1475 数组分拆【DP+前缀和优化】

    思路: DP[ i ] 代表以 i 结尾的方案数. dp[i] += sum[i] - sum[j - 1] != 0 ? dp[j] : 0 ; 对于100%的数据,满足1<=N<=10 ...

  9. SPOJ130 【DP·背包选取特性】

    题意: 给你n个任务,每个任务有一个起始时间,持续时间,一个权值: 问你怎么分配得到最大值 思路: 数据好大..百度了一发意识到自己好菜啊!背包的特性. dp[i]代表前 i 个能构成的最大值. 对于 ...

  10. lightoj1145 【DP优化求方案】

    题意: 有一个k面的骰子,然后问你n个骰子朝上的面数字之和=s的方案: 思路: dp[i][j] 代表 前 i 个骰子组成 j 有多少种方案: 显然 dp[i][j] = dp[i - 1][j - ...

随机推荐

  1. 半年收入超2亿RMB 独立游戏开发者的艰苦创业路

    一款叫做<监狱建筑师>的模拟经营游戏,目前在Steam平台获得了3000万美元(近2亿元)以上的收入.这款游戏由英国独立工作室Introversion Software发布,而团队最困难的 ...

  2. Scrum立会报告+燃尽图(Final阶段第六次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2485 项目地址:https://coding.net/u/wuyy694 ...

  3. Task 6.2冲刺会议十 /2015-5-23

    今天是第一个冲刺阶段的最后一天,主要把做出来的程序进行了初步的测试,在一台笔记本上运行程序,摄像头可以工作也能听到声音和麦克多的运转也还可以,两台计算机同时在一个局域网中通信的时候也可以实现.不过后续 ...

  4. 《UML大战需求分析》-读后感二

    活动图将流成分解为一个一个的活动,通过活动的先后顺序来展示流程,而状态机图是从某个事物的状态是如何转变的角度来展示流程,首先确定事物,然后找出状态,状态之间的箭头叫转换,箭头上的文字说明了是什么事情导 ...

  5. java小学生四则运算带面板版 但我不知道为什么同类变量却进不了动作监听中去

    ---恢复内容开始--- package yun; import java.util.*; import java.awt.*; import java.awt.event.ActionEvent; ...

  6. diliucizuoye

    NABCD N(Need 需求) 互联网的高速发展,造就了二十一世纪这个追求高品质.高体验的信息时代,随其发展改变的是信息记录与分享方式,从传统的面对面交流.手机通话.写日记本,到现如今的社交平台.信 ...

  7. 《软件工程和Python》第0周作业1

    写在前面的话 欢迎大家开始一段新的课程学习!从开博客开始吧.每次博客作业都会有评分,计入总成绩哦. 1.   截止日期 本次作业的提交截止时间:见老师要求 2.   作业要求 (1)建立个人技术博客和 ...

  8. YFCC 100M数据集分析笔记

    --从YFCC 100M数据集中筛选出Geo信息位于中国的数据集 1.YFCC 100M简介 YFCC 100M数据库是2014年来基于雅虎Flickr的影像数据库.该库由1亿条产生于2004年至20 ...

  9. mac下搭建MySql环境

    准备工作做完后,开始: 创建数据库 step1: 在mac中->系统偏好设置->最下边点MySQL 在弹出页面中 关闭mysql服务(点击stop mysql server) step2: ...

  10. mysubmail 短信报警

    https://www.mysubmail.com/chs/documents/developer/YPWD84   文本文档  官网:www.mysubmail.com 操作流程:快速接入短信 AP ...