codejam-Round1A-2008-Numbers

题意

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


分析

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

SolutionA

因为
an 可以写作 pn+qn5 的形式
同理, bn=pnqn5 所以 an+bn=2pn
因为 0<35<1 ,所以 0<bn<1 ,又因为 pn 必为整数,答案也为整数,所以答案就可表示为 pn1
所以,只要快速地求 pn 即可
(3+5)(pn1+qn15)=[3pn1+5qn1+(pn1+3qn1)5]
得到转移公式: pn=3pn1+5qn1 , qn=pn1+3qn1
再利用矩阵快速幂,求出结果即可

#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=2r=0n/2C2rn3n2r5r
(套用二项式定理暴力拆开即可)
solutionA已经说明, Xn 就是我们要的答案
观察发现:
a+b=6,ab=4
可以得到方程 x26x+4=0
所以 a2=6a4,b2=6b4
a3=6a24a,b3=6b24b
以此类推
an+2=6an+14an,bn+2=6bn+14bn
所以 xn+2=6xn+14xn
这就得到了转移公式,和solutionA一样,矩阵快速幂即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值