【codejam2008_Round1A_C】Numbers

来源:互联网 发布:酷狗上传的歌网络异常 编辑:程序博客网 时间:2024/06/09 14:54

题目大意:
计算(3+5)n整数部分末三位。

题解:
题解原网址https://code.google.com/codejam/contest/32016/dashboard#s=a&a=2

α=3+5β=35Xn=αn+βn
可证明Xn为整数(二项式定理)

Xn=αn+βn=i=0n(ni)3ni(5)i+i=0n(ni)3ni5i=2i=0n/2(n2i)3n2i5i

0<βn<1
αn的整数部分一定等于Xn1

Solution1:(共轭)

αn=an+bn5βn=anbn5
Xn=2an
αn+1=(3+5)(an+bn5)=(3an+5bn)+(an+3bn)5
an+1=3an+5bnbn+1=an+3bn

(anbn)=A(an1bn1)=An(a0b0),A=(3153)

初始状态:α0=1
(a0b0)=(10)

可使用矩阵快速幂,时间复杂度O(logn)

方法2:

α+β=6αβ=4
所以α和β是x26x+4=0的两个根
α2=6α4β2=6β4
αn+2=6αn+14αnβn+2=6βn+14βn
两式相加,得:

Xn+2=6Xn+14Xn

所以可使用矩阵乘法:
(Xn+1Xn)=B(XnXn1)=Bn(X1X0),B=(6140)

方法3:(方法2存在循环,可优化)

我们只需要最后结果的最后3位,经过法2的多次计算后发现,结果从n=4n=103是一个长度为100的循环,然后继续下去。
如果n很大,输出(n3)mod100+3

代码:

#include<cstdio>#include<vector>using namespace std;typedef vector<int> Vector;typedef vector<Vector> Matrix;Matrix operator * (Matrix a,Matrix b){    int as1=a.size(),as2=a[0].size(),bs1=b.size(),bs2=b[0].size();    if(as2!=bs1)        return Matrix(0,Vector(0));    Matrix ret(as2,Vector(bs1,0));    for(int i=0;i<as1;i++)        for(int j=0;j<bs2;j++)            for(int k=0;k<as2;k++)                ret[i][j]=(ret[i][j]+(a[i][k]*b[k][j])%1000)%1000;    return ret;}Matrix pow(Matrix a,int b){    Matrix c(a.size(),Vector(a.size(),0));    for(int i=0;i<(int)a.size();i++)        c[i][i]=1;          for(;b;b>>=1,a=a*a)        if(b&1)            c=c*a;    return c;}namespace SolutionA{    int solve(int n)    {        Matrix a(2,Vector(2,0));        a[0][0]=3;a[0][1]=5;        a[1][0]=1;a[1][1]=3;        a=pow(a,n);        return (a[0][0]*2+999)%1000;    }}namespace SolutionB{    int solve(int n)    {        Matrix b(2,Vector(2));        b[0][0]=6;b[0][1]=-4;        b[1][0]=1;b[1][1]=0;        b=pow(b,n);        int ret=b[1][0]*6+b[1][1]*2+999;        while(ret<0)            ret+=1000;        return ret%1000;    }}namespace SolutionC{    int solve(int n)    {        if(n>103)            n=(n-3)%100+3;        return SolutionB::solve(n);    }}int main(){    int T,n;    scanf("%d",&T);    for(int i=1;i<=T;i++)    {        scanf("%d",&n);        //printf("Case #%d: %03d\n",i,SolutionA::solve(n));        //printf("Case #%d: %03d\n",i,SolutionB::solve(n));        printf("Case #%d: %03d\n",i,SolutionC::solve(n));    }    return 0;}
原创粉丝点击