题意
求(3+√5)n次方的整数部分后三位
分析
乍一看觉得就是普通的一道快速幂的题,准备直接开搞,才发现因为√5无限不循环小数,这就使得整数部分即使在千位以上仍然会对百位以下造成影响(1000*0.1=1)。
想到这里,不难发现这是一道数学题。
观察这个式子(3+√5),不难想到一种常见套路——共轭
设
a=3+√5
,
b=3−√5
SolutionA
因为
an
可以写作
pn+qn√5
的形式
同理,
bn=pn−qn√5
所以
an+bn=2∗pn
因为
0<3−√5<1
,所以
0<bn<1
,又因为
pn
必为整数,答案也为整数,所以答案就可表示为
pn−1
所以,只要快速地求
pn
即可
(3+√5)(pn−1+qn−1√5)=[3∗pn−1+5∗qn−1+(pn−1+3∗qn−1)√5]
得到转移公式:
pn=3∗pn−1+5∗qn−1
,
qn=pn−1+3∗qn−1
再利用矩阵快速幂,求出结果即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MOD 1000
using namespace std;
int cnt;
struct node{
int a,b,c,d;
node(int aa,int bb,int cc,int dd):a(aa),b(bb),c(cc),d(dd) {}
node(){}
};
node s(node a,node b){
return node((a.a*b.a+a.b*b.c)%MOD,(a.a*b.b+a.b*b.d)%MOD,(a.c*b.a+a.d*b.c)%MOD,(a.d*b.d+a.c*b.b)%MOD);
}
node pow(int n){
if(n==1)
return node(3,5,1,3);
node x=pow(n/2);
if(n%2==1)
return s(node(3,5,1,3),s(x,x));
else
return s(x,x);
}
void work(int n){
node a=pow(n);
PF("Case #%d: %03d\n",++cnt,(a.a*2+MOD-1)%MOD);
}
int t;
int main(){
SF("%d",&t);
int x;
for(int o=1;o<=t;o++){
SF("%d",&x);
work(x);
}
}
SolutionB
设
Xn=aⁿ+bⁿ
根据二项式定理
Xn=aⁿ+bⁿ=2∗∑r=0n/2C2∗rn3n−2∗r∗5r
(套用二项式定理暴力拆开即可)
solutionA已经说明, Xn 就是我们要的答案
观察发现:
a+b=6,a∗b=4
可以得到方程 x2−6x+4=0
所以 a2=6a−4,b2=6b−4
a3=6a2−4a,b3=6b2−4b
以此类推
an+2=6an+1−4an,bn+2=6bn+1−4bn
所以 xn+2=6xn+1−4xn
这就得到了转移公式,和solutionA一样,矩阵快速幂即可。