Codeforces 1097 D Makoto and a Blackboard [概率+dp]

Codeforces 1097 D Makoto and a Blackboard

题目链接
题意:给定一个数 n n n,每次操作可以把 n n n等概率变成它的因数之一。求 k k k次操作之后 n n n的期望。

题解

每个质因子的贡献是分开的,比如质因子 p p p,当前幂次为 p k p^k pk,那么它会等概率变成 p 0 … p k p^0\dots p^k p0pk,于是直接对于每个质因子分开dp, f [ i ] [ j ] f[i][j] f[i][j]表示到第 i i i轮,幂次为 k k k的概率。则 f [ i ] [ j ] = ∑ k ≥ j f [ i − 1 ] [ k ] ⋅ 1 k + 1 f[i][j]=\sum_{k\ge j}f[i-1][k]\cdot \frac{1}{k+1} f[i][j]=kjf[i1][k]k+11,显然可以前缀和优化。于是总复杂度为 O ( k ⋅ ∑ 质 因 数 幂 次 ) O(k\cdot \sum质因数幂次) O(k).

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 10005, mod = 1000000007;
ll inv[maxn], n, k;
ll modpow(ll a, int b) {
	ll res = 1;
	for (; b; b >>= 1) {
		if (b & 1) res = res * a % mod;
		a = a * a % mod;
	}
	return res;
}
ll dv[maxn], ex[maxn], s[maxn], res = 1;
int main() {
	scanf("%lld%lld", &n, &k); ll m = n; int cnt = 0, all = 0;
	for (ll i = 2; i * i <= m; i++) if (m % i == 0) {
		++cnt, dv[cnt] = i;
		for (; m % i == 0; m /= i) ++ex[cnt], ++all;
	}
	if (m > 1) ++cnt, dv[cnt] = m, ++ex[cnt], ++all;
	inv[1] = 1;
	for (int i = 2; i < maxn; i++) inv[i] = mod - (ll)mod / i * inv[mod % i] % mod;
	for (int i = 1; i <= cnt; i++) {
		memset(s, 0, sizeof(s));
		s[ex[i]] = 1;
		for (int j = 1; j <= k; j++)
			for (int l = ex[i]; l >= 0; l--) s[l] = (s[l + 1] + s[l] * inv[l + 1]) % mod;
		ll mul = 1, sum = 0;
		for (int j = 0; j <= ex[i]; j++, (mul *= dv[i]) %= mod)
			sum = (sum + mul * s[j]) % mod;
		res = res * sum % mod;
	}
	printf("%lld\n", res);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值