「BZOJ 4833」[Lydsy1704月赛]最小公倍佩尔数

令 (1+2)n=e(n)+2⋅f(n)(1+\sqrt 2)^n=e(n)+\sqrt 2\cdot f(n) ,其中 e(n),f(n)e(n),f(n) 都是整数,显然有 (1−2)n=e(n)−2⋅f(n)(1-\sqrt 2)^n=e(n)-\sqrt 2\cdot f(n)。令 g(n)g(n) 表示 f(1),f(2),⋯,f(n)f(1),f(2),\cdots ,f(n) 的最小公倍数,给定两个正整数 nn 和 pp ,其中 pp 是质数,并且保证 f(1),f(2),⋯,f(n)f(1),f(2),\cdots ,f(n) 在模 pp 意义下均不为 00,请计算 ∑i=1ni⋅g(i)\sum _{i=1}^{n}i\cdot g(i) 模 pp 的值。

Constraints

T≤210T \leq 2 ^{10} ,1≤n≤1061\leq n \leq 10 ^6 ,2≤p≤109+72\leq p \leq 10 ^9 +7

Solution

在开始推导前先观察两个式子:

gcd(fib(a),fib(b))=fib(gcd(a,b))gcd(fib(a),fib(b))=fib(gcd(a,b))

gcd(xa−1,xb−1)=xgcd(a,b)−1gcd(x^a-1,x^b-1)=x^{gcd(a,b)}-1

形如 f(n)=a⋅f(n−1)+b⋅f(n−2)f(n)=a\cdot f(n-1)+b\cdot f(n-2) 的式子具有性质 gcd(f(x),f(y))=f(gcd(x,y))gcd(f(x),f(y))=f(gcd(x,y)) 。

而题目中的式子等价于: f(0)=0,f(1)=1,f(n)=2f(n−1)+f(n−2)f(0)=0,f(1)=1,f(n)=2f(n-1)+f(n-2),同样满足这个性质。

(以下集合 TT 均满足 $T\neq \varnothing $)

再由式子:

lcm(S)=∏T⊂Sgcd(T)(−1)∣T∣+1lcm(S)=\prod_{T\subset S}gcd(T)^{(-1)^{|T|+1}}

可以得到:

g(n)=∏T⊂2[n]f(gcdi∈T(i))(−1)∣T∣+1g(n)=\prod _{T\subset 2^{[n]}}f(gcd_{i\in T}(i))^{(-1)^{|T|+1}}

构造出 hh 满足 f(n)=∏d∣nh(d)f(n)=\prod _{d|n}h(d)

得到式子:

g(n)=∏T⊂2[n](∏d∣gcdi∈T(i)h(d))(−1)∣T∣+1=∏d=1nh(d)∑T⊂2 [⌊nd⌋] (−1)∣T∣+1\begin{aligned} g(n)&=\prod _{T\subset 2^{[n]}}\left ( \prod _{d|gcd_{i\in T}(i)}h(d) \right )^{(-1)^{|T|+1}}\\ &=\prod _{d=1}^{n}h(d)^{\sum _{T\subset 2^{~[\lfloor \frac{n}{d}\rfloor ]~}}(-1)^{|T|+1}} \end{aligned}

又由二项式定理可证:

∑T⊂2[⌊nd⌋](−1)∣T∣+1=−∑i=1nd(−1)i(ndi)=1\sum _{T\subset 2^{[\lfloor \frac{n}{d}\rfloor ]}}(-1)^{|T|+1}=-\sum _{i=1}^{\frac{n}{d}}(-1)^i\binom{\frac{n}{d}}{i}=1

所以 g(n)=∏d=1nh(d)g(n)=\prod _{d=1}^{n}h(d)

问题解决,时间复杂度 O(nlogn)O(nlogn)。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=1e6+5;
int T,n,mod,inv,sum,ans,f[N],h[N];
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 power(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;b>>=1;
}
return ans;
}
int main()
{
T=read();
while(T--)
{
n=read();mod=read();
f[0]=0;h[1]=f[1]=1;
for(int i=2;i<=n;i++)
h[i]=f[i]=(1ll*f[i-1]*2+f[i-2])%mod;
for(int i=1;i<=n;i++)
{
inv=power(h[i],mod-2);
for(int j=i+i;j<=n;j+=i)h[j]=1ll*h[j]*inv%mod;
}
sum=1;ans=0;
for(int i=1;i<=n;i++)
sum=1ll*sum*h[i]%mod,ans=(ans+1ll*sum*i)%mod;
printf("%d\n",ans);
}
return 0;
}