P1587 [NOI2016] 循环之美

P1587 [NOI2016] 循环之美

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

先思考怎么转换。

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

假设 x y \frac{x}{y} yx 的循环节长度为 l l l,根据在 k k k 进制下的数乘以 k p k^p kp 相当于将小数点往后挪 p p p 位,那么有:
{ x k l y } = { x y } \{\frac{xk^l}{y}\}=\{\frac{x}{y}\} {yxkl}={yx}
转换一下上面那个式子,有:
x k l y − ⌊ x k l y ⌋ = x y − ⌊ x y ⌋ x k l − ⌊ x k l y ⌋ ⋅ y = x − ⌊ x y ⌋ ⋅ y x k l ≡ x ( m o d y ) k l ≡ 1 ( m o d y ) 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} yxklyxklxklyxklyxklklgcd(k,y)=yxyx=xyxyx(mody)1(mody)=1
那么题意就可以转换为求:
∑ i = 1 n ∑ j = 1 m [ 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 = 1 n ∑ j = 1 m [ gcd ⁡ ( i , j ) = 1 ] [ gcd ⁡ ( j , k ) = 1 ] = ∑ i = 1 n ∑ j = 1 m [ gcd ⁡ ( j , k ) = 1 ] ∑ p ∣ gcd ⁡ ( i , j ) μ ( p ) = ∑ i = 1 n ∑ j = 1 m [ gcd ⁡ ( j , k ) = 1 ] ∑ p = 1 min ⁡ ( n , m ) μ ( p ) [ p ∣ i ] [ p ∣ j ] = ∑ p = 1 min ⁡ ( n , m ) μ ( p ) ∑ i = 1 n ∑ j = 1 m [ p ∣ i ] [ p ∣ j ] [ gcd ⁡ ( j , k ) = 1 ] = ∑ p = 1 min ⁡ ( n , m ) μ ( p ) ∑ p ∣ i n ∑ p ∣ j m [ gcd ⁡ ( j , k ) = 1 ] = ∑ p = 1 min ⁡ ( n , m ) μ ( p ) ⌊ n p ⌋ ∑ p ∣ j m [ gcd ⁡ ( j , k ) = 1 ] = ∑ p = 1 min ⁡ ( n , m ) μ ( p ) [ gcd ⁡ ( p , k ) = 1 ] ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ [ 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} 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)pnpjm[gcd(j,k)=1]=p=1min(n,m)μ(p)[gcd(p,k)=1]pnj=1pm[gcd(j,k)=1]

再设个函数,并化简:
f ( n ) = ∑ i = 1 n [ gcd ⁡ ( i , k ) = 1 ] \begin{aligned} f(n)=\sum_{i=1}^{n}[\gcd(i,k)=1] \end{aligned} f(n)=i=1n[gcd(i,k)=1]

思考,当 i > k i>k i>k 时,有 gcd ⁡ ( i , k ) = gcd ⁡ ( i + k , k ) \gcd(i,k)=\gcd(i+k,k) gcd(i,k)=gcd(i+k,k),那么答案肯定是呈现一个长度为 k k k 的循环,那么有:
f ( n ) = f ( n   m o d   k ) + ⌊ n k ⌋ φ ( k ) \begin{aligned} f(n) &=f(n \bmod k)+\lfloor\frac{n}{k}\rfloor\varphi(k) \end{aligned} f(n)=f(nmodk)+knφ(k)
那么原式等于:
∑ p = 1 min ⁡ ( n , m ) ⌊ n p ⌋ f ( ⌊ m p ⌋ ) μ ( 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] p=1min(n,m)pnf(pm)μ(p)[gcd(p,k)=1]
现在已经有整除分块了,然后是处理 ∑ i = 1 n μ ( i ) [ gcd ⁡ ( i , k ) = 1 ] \sum\limits_{i=1}^{n}\mu(i)[\gcd(i,k)=1] i=1nμ(i)[gcd(i,k)=1] 前缀和的问题。

法一

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

尝试化简 s ( n , k ) s(n,k) s(n,k),则有:
s ( n , k ) = ∑ i = 1 n μ ( i ) [ gcd ⁡ ( i , k ) = 1 ] = ∑ i = 1 n μ ( i ) ∑ p = 1 min ⁡ ( n , k ) μ ( p ) [ p ∣ i ] [ p ∣ k ] = ∑ p ∣ k min ⁡ ( n , k ) μ ( p ) ∑ p ∣ i n μ ( i ) = ∑ p ∣ k min ⁡ ( n , k ) μ ( p ) ∑ i = 1 ⌊ n p ⌋ μ ( i p ) = ∑ p ∣ k min ⁡ ( n , k ) μ ( p ) 2 ∑ i = 1 ⌊ n p ⌋ μ ( i ) [ gcd ⁡ ( i , p ) = 1 ] = ∑ p ∣ k min ⁡ ( n , k ) μ ( p ) 2 s ( ⌊ n p ⌋ , 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,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=1pnμ(ip)=pkmin(n,k)μ(p)2i=1pnμ(i)[gcd(i,p)=1]=pkmin(n,k)μ(p)2s(pn,p)

然后数论分块即可。

法二

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

s ( n ) = ∑ i = 1 n μ ( i ) [ gcd ⁡ ( i , k ) = 1 ] = ∑ i = 1 n [ gcd ⁡ ( i , k ) = 1 ] s ( ⌊ n i ⌋ ) − ∑ i = 2 n [ gcd ⁡ ( i , k ) = 1 ] s ( ⌊ n i ⌋ ) \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} s(n)=i=1nμ(i)[gcd(i,k)=1]=i=1n[gcd(i,k)=1]s(in)i=2n[gcd(i,k)=1]s(in)
先看前面那个:
∑ i = 1 n [ gcd ⁡ ( i , k ) = 1 ] s ( ⌊ n i ⌋ ) = ∑ i = 1 n [ gcd ⁡ ( i , k ) = 1 ] ∑ j = 1 ⌊ n i ⌋ μ ( j ) [ gcd ⁡ ( j , k ) = 1 ] = ∑ i = 1 n ∑ j = 1 ⌊ n i ⌋ μ ( j ) [ gcd ⁡ ( i j , k ) = 1 ] = ∑ t = 1 n ∑ d ∣ t [ gcd ⁡ ( t , k ) = 1 ] μ ( d ) = ∑ t = 1 n [ 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} i=1n[gcd(i,k)=1]s(in)=i=1n[gcd(i,k)=1]j=1inμ(j)[gcd(j,k)=1]=i=1nj=1inμ(j)[gcd(ij,k)=1]=t=1ndt[gcd(t,k)=1]μ(d)=t=1n[gcd(t,k)=1][t=1]=1
那么最终有:
s ( n ) = 1 − ∑ i = 2 n [ gcd ⁡ ( i , k ) = 1 ] s ( ⌊ n i ⌋ ) s(n)=1-\sum_{i=2}^{n}[\gcd(i,k)=1]s(\lfloor\frac{n}{i}\rfloor) s(n)=1i=2n[gcd(i,k)=1]s(in)
数论分块即可。

#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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值