[BZOJ4833] [Lydsy1704月赛]最小公倍佩尔数(Min-Max 容斥)

题意

  • ( 1 + 2 ) n = e ( n ) + 2 f ( n ) , g ( n ) = lcm ( f ( 1 ) , f ( 2 ) , . . . , f ( n ) ) (1+\sqrt 2)^n=e(n)+\sqrt 2f(n),g(n)=\text{lcm}(f(1),f(2),...,f(n)) (1+2 )n=e(n)+2 f(n),g(n)=lcm(f(1),f(2),...,f(n)),求 ∑ i = 1 n g ( i ) × i \sum\limits_{i = 1}^ng(i)\times i i=1ng(i)×i。( n ≤ 1 0 6 n\le10^6 n106

挺巧妙的数学题,全程对着题解抄的,要推出来脑洞得足够大。

首先可以知道: f ( n ) = 2 f ( n − 1 ) + f ( n − 2 ) f(n)=2f(n-1)+f(n-2) f(n)=2f(n1)+f(n2)

引理一:对于 f ( n ) = a f ( n − 1 ) + b f ( n − 2 ) f(n)=af(n-1)+bf(n-2) f(n)=af(n1)+bf(n2) 形式的递推式,如果有 gcd ⁡ ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1,那么 gcd ⁡ ( f ( a ) , f ( b ) ) = f ( gcd ⁡ ( a , b ) ) \gcd(f(a),f(b))=f(\gcd(a,b)) gcd(f(a),f(b))=f(gcd(a,b)),具体可以联系辗转相除的过程用归纳法证明。

引理二:
lcm ( S ) = ∏ T ⊂ S ( − 1 ) ∣ T ∣ + 1 gcd ⁡ ( T ) ( T ≠ ϕ ) \text{lcm}(S)=\prod_{T\subset S}(-1)^{|T|+1}\gcd(T)(T\neq\phi) lcm(S)=TS(1)T+1gcd(T)(T̸=ϕ)
具体证明把 lcm \text {lcm} lcm 看做指数取最大值, g c d \rm gcd gcd 看做指数取最小值,套用 Min-Max 容斥即可。

定义 U = { 1 , 2 , . . . , n } U=\{1,2,...,n\} U={1,2,...,n} h h h 满足 f ( n ) = ∏ d ∣ n h ( d ) f(n)=\prod\limits_{d|n}h(d) f(n)=dnh(d),那么 h ( n ) = f ( n ) ∏ d ∣ n , d ≠ n h ( d ) h(n)=\frac{f(n)}{\displaystyle\prod_{d|n,d\neq n}h(d)} h(n)=dn,d̸=nh(d)f(n),我们可以 O ( n ln ⁡ n ) O(n \ln n) O(nlnn) 枚举倍数计算。

由引理一和引理二可知:
g ( n ) = ∏ T ⊂ U ( − 1 ) ∣ T ∣ + 1 f ( gcd ⁡ i ∈ T i ) g ( n ) = ∏ T ⊂ U ( − 1 ) ∣ T ∣ + 1 ∏ d ∣ gcd ⁡ i ∈ T i h d g(n)=\prod_{T\subset U}(-1)^{|T|+1}f(\gcd_{i\in T}i)\\ g(n)=\prod_{T\subset U}(-1)^{|T|+1}\prod_{d|\gcd\limits_{i\in T}i}h_d g(n)=TU(1)T+1f(iTgcdi)g(n)=TU(1)T+1diTgcdihd
S d = { d , 2 d , . . . , ⌊ n d ⌋ } S_d=\{d,2d,...,\lfloor\frac n d \rfloor\} Sd={d,2d,...,dn},那么:
g ( n ) = ∏ d = 1 n h d ∑ T ⊂ S d ( − 1 ) ∣ T ∣ + 1 g(n)=\prod_{d = 1}^nh_d^{\sum\limits_{T\subset S_d}(-1)^{|T|+1}} g(n)=d=1nhdTSd(1)T+1

又因为 ∑ T ⊂ S d ( − 1 ) ∣ T ∣ + 1 = ∑ i = 1 ∣ S d ∣ ( − 1 ) i + 1 ( ∣ S d ∣ i ) \sum\limits_{T\subset S_d}(-1)^{|T|+1}=\sum\limits_{i = 1}^{|S_d|}(-1)^{i+1}\binom {|S_d|} i TSd(1)T+1=i=1Sd(1)i+1(iSd),由二项式定理可知后面这个东西等于一,所以 g ( n ) = ∏ d = 1 n h d g(n)=\prod\limits_{d = 1}^nh_d g(n)=d=1nhd

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int T, n, Mod, h[N], f[N];

inline int qpow(int a, int x)
{
	int ret = 1; 
	for (; x; x >>= 1, a = 1ll * a * a % Mod)
		if (x & 1) ret = 1ll * ret * a % Mod;
	return ret;
}

int main()
{
#ifdef ylsakioi
	freopen("4833.in", "r", stdin);
	freopen("4833.out", "w", stdout);
#endif
	f[0] = 0, f[1] = h[1] = 1;
	for (scanf("%d", &T); T -- ; )
	{
		scanf("%d%d", &n, &Mod);
		for (int i = 2; i <= n; ++ i)
			h[i] = f[i] = (2ll * f[i - 1] + f[i - 2]) % Mod;
		for (int i = 2; i <= n; ++ i)
		{
			int d = qpow(h[i], Mod - 2);
			for (int j = i << 1; j <= n; j += i) 
				h[j] = 1ll * h[j] * d % Mod;
		}
		int ans = 0, ret = 1; 
		for (int i = 1; i <= n; ++ i) 
		{
			ret = 1ll * ret * h[i] % Mod;
			(ans += 1ll * ret * i % Mod) %= Mod;
		}
		printf("%d\n", ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值