当前位置: 代码迷 >> 综合 >> codejam-Round1A-2008-Numbers
  详细解决方案

codejam-Round1A-2008-Numbers

热度:136   发布时间:2023-09-27 08:59:27.0

题意

求(3+√5)n次方的整数部分后三位


分析

乍一看觉得就是普通的一道快速幂的题,准备直接开搞,才发现因为√5无限不循环小数,这就使得整数部分即使在千位以上仍然会对百位以下造成影响(1000*0.1=1)。
想到这里,不难发现这是一道数学题。
观察这个式子(3+√5),不难想到一种常见套路——共轭
a=3+5,b=3?5

SolutionA

因为
an可以写作pn+qn5的形式
同理,bn=pn?qn5所以an+bn=2?pn
因为 0<3?5<1,所以0<bn<1,又因为pn必为整数,答案也为整数,所以答案就可表示为pn?1
所以,只要快速地求pn即可
(3+5)(pn?1+qn?15)=[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));elsereturn 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一样,矩阵快速幂即可。

  相关解决方案