• 【Codeforces1139D_CF1139D】Steps to One (Mobius_DP)


    Problem:

    Codeforces 1139D

    Analysis:

    After ACing E, I gave up D and spent the left 30 minutes chatting with Little Dino.

    Let (f[n]) be the expected number of steps needed to make the greatest common divisor (gcd) become (1) when the gcd is (n) now, and (g(n,d)) be the number of (x(xin[1,m])) that (gcd(x, n)=d) . So we have:

    [f[n]=1+sum_{d|n}frac{f[d]cdot g(n, d)}{m} ]

    To make it easy, multiply (m) to the equation:

    [mf[n]=m+sum_{d|n}f[d]cdot g(n, d) ]

    Notice that (d) can be (n), and (g(n,n)) is (lfloorfrac{m}{n} floor), so we have:

    [(m-lfloorfrac{m}{n} floor)f[n]=m+sum_{d|n,d eq n}f[d]cdot g(n, d) ]

    Now the problem become how to calculate (g(n,d)). According to the defination,

    [egin{aligned} g(n, d)&=sum_{i=1}^m[gcd(n, i)=d]\ &=sum_{i=1}^{lfloorfrac{m}{d} floor}[gcd(frac{n}{d},i)=1]\ &=sum_{i=1}^{lfloorfrac{m}{d} floor}epsilonleft(gcd(frac{n}{d},i) ight)\ end{aligned} ]

    where (epsilon(x)=egin{cases}1 (x=1)\0 mathrm{otherwise}end{cases}) .

    According to the Mobius Theorem ( (mu * 1 = epsilon) ) :

    [egin{aligned} g(n,d)&=sum_{i=1}^{lfloorfrac{m}{d} floor}sum_{t|frac{n}{d},t|i}mu(t)\ &=sum_{t|frac{n}{d}}mu(t)cdot lfloor frac{m}{dt} floor end{aligned} ]

    Let's return to (f[n]):

    [(m-lfloorfrac{m}{n} floor)f[n]=m+sum_{d|n,d eq n}f[d]sum_{t|frac{n}{d}}mu(t)cdot lfloor frac{m}{dt} floor ]

    Preprocess the divisors of all integer (x(xin[1,m])) and then calculate (f[n]) as the equation above directly. Because the number of divisors of most integers is very small ( for integers not more than (100000), the maximum is (128) and the total number is about (10^6) to (2 imes 10^6)) , so it won't TLE.

    At last, the answer is:

    [ans=1+sum_{i=1}^{m}frac{f[i]}{m} ]

    Code:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    namespace zyt
    {
    	typedef long long ll;
    	const int N = 1e5 + 10, p = 1e9 + 7;
    	vector<int> fac[N];
    	int n, f[N], pcnt, prime[N], mu[N];
    	bool mark[N];
    	void init()
    	{
    		for (int i = 1; i <= n; i++)
    			for (int j = 1; j * j <= i; j++)
    				if (i % j == 0)
    				{
    					fac[i].push_back(j);
    					if (j * j != i)
    						fac[i].push_back(i / j);
    				}
    		mu[1] = 1;
    		for (int i = 2; i <= n; i++)
    		{
    			if (!mark[i])
    				prime[pcnt++] = i, mu[i] = p - 1;
    			for (int j = 0; j < pcnt && (ll)i * prime[j] <= n; j++)
    			{
    				int k = i * prime[j];
    				mark[k] = true;
    				if (i % prime[j] == 0)
    				{
    					mu[k] = 0;
    					break;
    				}
    				else
    					mu[k] = p - mu[i];
    			}
    		}
    	}
    	int power(int a, int b)
    	{
    		int ans = 1;
    		while (b)
    		{
    			if (b & 1)
    				ans = (ll)ans * a % p;
    			a = (ll)a * a % p;
    			b >>= 1;
    		}
    		return ans;
    	}
    	int inv(const int a)
    	{
    		return power(a, p - 2);
    	}
    	int work()
    	{
    		scanf("%d", &n);
    		init();
    		f[1] = 0;
    		int ans = 0;
    		for (int i = 2; i <= n; i++)
    		{
    			for (int j = 0; j < fac[i].size(); j++)
    			{
    				int d = fac[i][j];
    				if (d == i)
    					continue;
    				int tmp = 0;
    				for (int k = 0, size = fac[i / d].size(); k < size; k++)
    				{
    					int t = fac[i / d][k];
    					tmp = (tmp + (ll)mu[t] * (n / d / t) % p) % p;
    				}
    				f[i] = (f[i] + (ll)tmp * f[d] % p) % p;
    			}
    			f[i] = (ll)(f[i] + n) * inv(n - n / i) % p;
    		}
    		for (int i = 1; i <= n; i++)
    			ans = (ans + f[i]) % p;
    		printf("%d", int(((ll)ans * inv(n) % p) + 1) % p);
    		return 0;
    	}
    }
    int main()
    {
    	return zyt::work();
    }
    
  • 相关阅读:
    hadoop集群配置和测试
    ubuntu 12.04安装jdk
    springboot集成mybatis
    redis连接数据库
    生产随机数
    关于字符串统计次数
    闲的无聊写了一个房租的后台
    简单的死锁
    java集合类总结(转)
    mybatis框架的搭建
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/10584706.html
Copyright © 2020-2023  润新知