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

(1+2)n=e(n)+2f(n)(1+\sqrt 2)^n=e(n)+\sqrt 2\cdot f(n) ,其中 e(n),f(n)e(n),f(n) 都是整数,显然有 (12)n=e(n)2f(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) 的最小公倍数,给定两个正整数 nnpp ,其中 pp 是质数,并且保证 f(1),f(2),,f(n)f(1),f(2),\cdots ,f(n) 在模 pp 意义下均不为 00,请计算 i=1nig(i)\sum _{i=1}^{n}i\cdot g(i)pp 的值。

Constraints

T210T \leq 2 ^{10}1n1061\leq n \leq 10 ^62p109+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(xa1,xb1)=xgcd(a,b)1gcd(x^a-1,x^b-1)=x^{gcd(a,b)}-1

形如 f(n)=af(n1)+bf(n2)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(n1)+f(n2)f(0)=0,f(1)=1,f(n)=2f(n-1)+f(n-2),同样满足这个性质。

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

再由式子:

lcm(S)=TSgcd(T)(1)T+1lcm(S)=\prod_{T\subset S}gcd(T)^{(-1)^{|T|+1}}

可以得到:

g(n)=T2[n]f(gcdiT(i))(1)T+1g(n)=\prod _{T\subset 2^{[n]}}f(gcd_{i\in T}(i))^{(-1)^{|T|+1}}

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

得到式子:

g(n)=T2[n](dgcdiT(i)h(d))(1)T+1=d=1nh(d)T2 [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}

又由二项式定理可证:

T2[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;
}