• CF1097D Makoto and a Blackboard(期望)


    link

    题目大意:给您一个数 n, 每次从n的所有约数(包含1、n)中等概率选出一个约数替换n,重复操作k次,求最后结果期望值%1e9+7。

    题解:考虑暴力,我们设f(n,k)代表答案,则有f(n,k)=sum_{d|n}f(d,k-1)。f(n,0)=n。

    我们发现如果把n分解质因数,最后结果就是所有质因子若干次方结果乘积(f是积性函数)。

    分解质因数后,我们设g(n,k)代表p^n次方执行k次的结果,由于n是log级别的,所以可以直接dp了。

    最后得到了p^0…p^n的分布,加起来乘到答案里就行了。

    代码

    #include <cstdio>
    using namespace std;
    
    const int xkj = 1000000007;
    
    long long n, k, tmp;
    long long d[30];
    int p[30], tot;
    int f[60], g[60], inv[60];
    
    int qpow(int x, int y)
    {
    	int res = 1;
    	for (x %= xkj; y > 0; y >>= 1, x = x * (long long)x % xkj)
    		if (y & 1) res = res * (long long)x % xkj;
    	return res;
    }
    
    int work(long long p, int m)
    {
    	for (int i = 0; i < m; i++) f[i] = 0;
    	f[m] = 1;
    	for (int t = 1; t <= k; t++)
    	{
    		for (int i = 0; i <= m; i++) g[i] = 0;
    		for (int i = 0; i <= m; i++)
    		{
    			f[i] = f[i] * (long long)inv[i + 1] % xkj;
    			for (int j = 0; j <= i; j++)
    			{
    				g[j] = (g[j] + f[i]) % xkj;
    			}
    		}
    		for (int i = 0; i <= m; i++) f[i] = g[i];
    	}
    	int res = 0, tmp = 1; p %= xkj;
    	for (int j = 0; j <= m; j++) res = (res + f[j] * (long long)tmp % xkj) % xkj, tmp = tmp * p % xkj;
    	return res;
    }
    
    int main()
    {
    	scanf("%lld%lld", &n, &k); tmp = n;
    	for (int i = 0; i < 60; i++) inv[i] = qpow(i, xkj - 2);
    	for (int i = 2; i * (long long)i <= n; i++)
    	{
    		if (tmp % i == 0)
    		{
    			d[++tot] = i, p[tot] = 1, tmp /= i;
    			while (tmp % i == 0) tmp /= i, p[tot]++;
    		}
    	}
    	if (tmp > 1) d[++tot] = tmp, p[tot] = 1;
    	int ans = 1;
    	for (int i = 1; i <= tot; i++) ans = ans * (long long)work(d[i], p[i]) % xkj;
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    django 2.0 path
    Django
    ORM
    Django简介
    web框架
    HTTP协议
    web应用
    索引
    pyMysql模块
    视图、触发器、存储过程、函数
  • 原文地址:https://www.cnblogs.com/oier/p/10596729.html
Copyright © 2020-2023  润新知