P1587 [NOI2016] 循环之美

P1587 [NOI2016] 循环之美

求 ∑x=1n∑y=1mxy\sum\limits_{x=1}^n\sum\limits_{y=1}^m\frac{x}{y} 在 kk 进制下能表示成循环节从第一位小数开始的无限循环小数或整数的最简分数个数。

先思考怎么转换。

首先肯定满足 gcd⁡(x,y)=1\gcd(x,y)=1。

假设 xy\frac{x}{y} 的循环节长度为 ll,根据在 kk 进制下的数乘以 kpk^p 相当于将小数点往后挪 pp 位,那么有:

{xkly}={xy}\{\frac{xk^l}{y}\}=\{\frac{x}{y}\}

转换一下上面那个式子,有:

xkly−⌊xkly⌋=xy−⌊xy⌋xkl−⌊xkly⌋⋅y=x−⌊xy⌋⋅yxkl≡x(mody)kl≡1(mody)gcd⁡(k,y)=1\begin{aligned} \frac{xk^l}{y}-\lfloor\frac{xk^l}{y}\rfloor&=\frac{x}{y}-\lfloor\frac{x}{y}\rfloor\\ xk^l-\lfloor\frac{xk^l}{y}\rfloor\cdot y&=x-\lfloor\frac{x}{y}\rfloor\cdot y\\ xk^l &\equiv x \pmod y\\ k^l &\equiv 1 \pmod y\\ \gcd(k,y)&=1 \end{aligned}

那么题意就可以转换为求:

∑i=1n∑j=1m[gcd⁡(i,j)=1][gcd⁡(j,k)=1]\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=1][\gcd(j,k)=1]

先化简原式,有:

∑i=1n∑j=1m[gcd⁡(i,j)=1][gcd⁡(j,k)=1]=∑i=1n∑j=1m[gcd⁡(j,k)=1]∑p∣gcd⁡(i,j)μ(p)=∑i=1n∑j=1m[gcd⁡(j,k)=1]∑p=1min⁡(n,m)μ(p)[p∣i][p∣j]=∑p=1min⁡(n,m)μ(p)∑i=1n∑j=1m[p∣i][p∣j][gcd⁡(j,k)=1]=∑p=1min⁡(n,m)μ(p)∑p∣in∑p∣jm[gcd⁡(j,k)=1]=∑p=1min⁡(n,m)μ(p)⌊np⌋∑p∣jm[gcd⁡(j,k)=1]=∑p=1min⁡(n,m)μ(p)[gcd⁡(p,k)=1]⌊np⌋∑j=1⌊mp⌋[gcd⁡(j,k)=1]\begin{aligned} &\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=1][\gcd(j,k)=1]\\ &=\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(j,k)=1]\sum_{p|\gcd(i,j)}\mu(p)\\ &=\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(j,k)=1]\sum_{p=1}^{\min(n,m)}\mu(p)[p|i][p|j]\\ &=\sum_{p=1}^{\min(n,m)}\mu(p)\sum_{i=1}^{n}\sum_{j=1}^{m}[p|i][p|j][\gcd(j,k)=1]\\ &=\sum_{p=1}^{\min(n,m)}\mu(p)\sum_{p|i}^{n}\sum_{p|j}^{m}[\gcd(j,k)=1]\\ &=\sum_{p=1}^{\min(n,m)}\mu(p)\lfloor\frac{n}{p}\rfloor\sum_{p|j}^{m}[\gcd(j,k)=1]\\ &=\sum_{p=1}^{\min(n,m)}\mu(p)[\gcd(p,k)=1]\lfloor\frac{n}{p}\rfloor\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[\gcd(j,k)=1]\\ \end{aligned}

再设个函数,并化简:

f(n)=∑i=1n[gcd⁡(i,k)=1]\begin{aligned} f(n)=\sum_{i=1}^{n}[\gcd(i,k)=1] \end{aligned}

思考,当 i>ki>k 时,有 gcd⁡(i,k)=gcd⁡(i+k,k)\gcd(i,k)=\gcd(i+k,k),那么答案肯定是呈现一个长度为 kk 的循环,那么有:

f(n)=f(n mod k)+⌊nk⌋φ(k)\begin{aligned} f(n) &=f(n \bmod k)+\lfloor\frac{n}{k}\rfloor\varphi(k) \end{aligned}

那么原式等于:

∑p=1min⁡(n,m)⌊np⌋f(⌊mp⌋)μ(p)[gcd⁡(p,k)=1]\sum_{p=1}^{\min(n,m)}\lfloor\frac{n}{p}\rfloor f(\lfloor\frac{m}{p}\rfloor)\mu(p)[\gcd(p,k)=1]

现在已经有整除分块了,然后是处理 ∑i=1nμ(i)[gcd⁡(i,k)=1]\sum\limits_{i=1}^{n}\mu(i)[\gcd(i,k)=1] 前缀和的问题。

法一

设前面那个式子为 s(n,k)s(n,k)。

尝试化简 s(n,k)s(n,k),则有:

s(n,k)=∑i=1nμ(i)[gcd⁡(i,k)=1]=∑i=1nμ(i)∑p=1min⁡(n,k)μ(p)[p∣i][p∣k]=∑p∣kmin⁡(n,k)μ(p)∑p∣inμ(i)=∑p∣kmin⁡(n,k)μ(p)∑i=1⌊np⌋μ(ip)=∑p∣kmin⁡(n,k)μ(p)2∑i=1⌊np⌋μ(i)[gcd⁡(i,p)=1]=∑p∣kmin⁡(n,k)μ(p)2s(⌊np⌋,p)\begin{aligned} s(n,k)&=\sum_{i=1}^{n}\mu(i)[\gcd(i,k)=1]\\ &=\sum_{i=1}^{n}\mu(i)\sum_{p=1}^{\min(n,k)}\mu(p)[p|i][p|k]\\ &=\sum_{p|k}^{\min(n,k)}\mu(p)\sum_{p|i}^{n}\mu(i)\\ &=\sum_{p|k}^{\min(n,k)}\mu(p)\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\mu(ip)\\ &=\sum_{p|k}^{\min(n,k)}\mu(p)^2\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\mu(i)[\gcd(i,p)=1]\\ &=\sum_{p|k}^{\min(n,k)}\mu(p)^2s(\lfloor\frac{n}{p}\rfloor,p) \end{aligned}

然后数论分块即可。

法二

这里是设前面那个式子为 s(n)s(n),则有:

s(n)=∑i=1nμ(i)[gcd⁡(i,k)=1]=∑i=1n[gcd⁡(i,k)=1]s(⌊ni⌋)−∑i=2n[gcd⁡(i,k)=1]s(⌊ni⌋)\begin{aligned} s(n)&=\sum_{i=1}^{n}\mu(i)[\gcd(i,k)=1]\\ &=\sum_{i=1}^{n}[\gcd(i,k)=1]s(\lfloor\frac{n}{i}\rfloor)-\sum_{i=2}^{n}[\gcd(i,k)=1]s(\lfloor\frac{n}{i}\rfloor) \end{aligned}

先看前面那个:

∑i=1n[gcd⁡(i,k)=1]s(⌊ni⌋)=∑i=1n[gcd⁡(i,k)=1]∑j=1⌊ni⌋μ(j)[gcd⁡(j,k)=1]=∑i=1n∑j=1⌊ni⌋μ(j)[gcd⁡(ij,k)=1]=∑t=1n∑d∣t[gcd⁡(t,k)=1]μ(d)=∑t=1n[gcd⁡(t,k)=1][t=1]=1\begin{aligned} &\sum_{i=1}^{n}[\gcd(i,k)=1]s(\lfloor\frac{n}{i}\rfloor)\\&=\sum_{i=1}^{n}[\gcd(i,k)=1]\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}\mu(j)[\gcd(j,k)=1]\\ &=\sum_{i=1}^{n}\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}\mu(j)[\gcd(ij,k)=1]\\ &=\sum_{t=1}^{n}\sum_{d|t}[\gcd(t,k)=1]\mu(d)\\ &=\sum_{t=1}^{n}[\gcd(t,k)=1][t=1]\\ &=1 \end{aligned}

那么最终有:

s(n)=1−∑i=2n[gcd⁡(i,k)=1]s(⌊ni⌋)s(n)=1-\sum_{i=2}^{n}[\gcd(i,k)=1]s(\lfloor\frac{n}{i}\rfloor)

数论分块即可。

#include <bits/stdc++.h>

using namespace std;

const int _ = 1e6 + 5;

inline int read()
{
	int x = 0, f = 1;
	char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}

int n, m, k;

int g[2007], A[_];

int cnt, vis[_], pri[_], mu[_];

map<int, int> ans_A;

long long ans;

int f(int n)
{
	return g[n % k] + (n / k) * g[k];
}

void init()
{
	for(int i = 1; i <= k; ++i) g[i] = g[i - 1] + (__gcd(i, k) == 1);
	mu[1] = A[1] = 1;
	for(int i = 2; i <= _ - 5; ++i)
	{
		if(!vis[i])
		{
			mu[i] = -1;
			pri[++cnt] = i;
		}
		for(int j = 1; j <= cnt && i * pri[j] <= _ - 5; ++j)
		{
			int p = i * pri[j];
			vis[p] = 1;
			if(i % pri[j] == 0) break;
			mu[p] = -mu[i];
		}
		A[i] = A[i - 1] + mu[i] * (f(i) - f(i - 1));
	}
}

int F(int x)
{
	if(x <= _ - 5) return A[x];
	if(ans_A.find(x) != ans_A.end()) return ans_A[x];
	int ans = 1;
	for(int l = 2, r; l <= x; l = r + 1)
	{
		r = x / (x / l);
		ans -= F(x / l) * (f(r) - f(l - 1));
	}
	return ans_A[x] = ans;	
}

signed main()
{
	n = read(), m = read(), k = read();
	init();
	for(int l = 1, r; l <= min(n, m); l = r + 1)
	{
		r = min(n / (n / l), m / (m / l));
		ans += 1LL * (n / l) * f(m / l) * (F(r) - F(l - 1));
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2022-01-12 13:34  蒟蒻orz  阅读(43)  评论(0)    收藏  举报  来源