【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(x\in[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 \(\lfloor\frac{m}{n}\rfloor\), so we have:

\[(m-\lfloor\frac{m}{n}\rfloor)f[n]=m+\sum_{d|n,d\neq n}f[d]\cdot g(n, d) \]

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

\[\begin{aligned} g(n, d)&=\sum_{i=1}^m[gcd(n, i)=d]\\ &=\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}[gcd(\frac{n}{d},i)=1]\\ &=\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}\epsilon\left(gcd(\frac{n}{d},i)\right)\\ \end{aligned} \]

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

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

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

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

\[(m-\lfloor\frac{m}{n}\rfloor)f[n]=m+\sum_{d|n,d\neq n}f[d]\sum_{t|\frac{n}{d}}\mu(t)\cdot \lfloor \frac{m}{dt} \rfloor \]

Preprocess the divisors of all integer \(x(x\in[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\times 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();
}
posted @ 2019-03-23 17:17  Inspector_Javert  阅读(761)  评论(0编辑  收藏  举报