P1587 [NOI2016] 循环之美

P1587 [NOI2016] 循环之美

x=1ny=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}\}

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

xklyxkly=xyxyxklxklyy=xxyyxklx(mody)kl1(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=1nj=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=1nj=1m[gcd(i,j)=1][gcd(j,k)=1]=i=1nj=1m[gcd(j,k)=1]pgcd(i,j)μ(p)=i=1nj=1m[gcd(j,k)=1]p=1min(n,m)μ(p)[pi][pj]=p=1min(n,m)μ(p)i=1nj=1m[pi][pj][gcd(j,k)=1]=p=1min(n,m)μ(p)pinpjm[gcd(j,k)=1]=p=1min(n,m)μ(p)nppjm[gcd(j,k)=1]=p=1min(n,m)μ(p)[gcd(p,k)=1]npj=1mp[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(nmodk)+nkφ(k)\begin{aligned} f(n) &=f(n \bmod k)+\lfloor\frac{n}{k}\rfloor\varphi(k) \end{aligned}

那么原式等于:

p=1min(n,m)npf(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)[pi][pk]=pkmin(n,k)μ(p)pinμ(i)=pkmin(n,k)μ(p)i=1npμ(ip)=pkmin(n,k)μ(p)2i=1npμ(i)[gcd(i,p)=1]=pkmin(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=1niμ(j)[gcd(j,k)=1]=i=1nj=1niμ(j)[gcd(ij,k)=1]=t=1ndt[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)=1i=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  阅读(6)  评论(0编辑  收藏  举报  来源