HDU 2842

f(n)代表把n个环全部拿下来要用的次数
要将第n个拿下, 前n-2个要拿下来,所以要用f(n-2)+1,
并且第n-1个在环上,要将第n-1个拿下来,必须前n-2个环要放回去即f(n-2)
然后再拿下前n-3,然后才拿下第n-1个,即(f(n-3)+1)
然后
再把前n-3个放回去,。。。一直循环得到: f(n)=f(n-2)+1+f(n-2)+f(n-3)+1+f(n-3)+......+f(n-n);
于是递推公式为:f(n)=2*f(n-2)+f(n-1)+1;
矩阵快速幂

 

#include <iostream>
#include <string.h>
using namespace std;
long n;
struct M{
    long long t[3][3];          //用long long,不能用int和long。。。。被坑了1次.....
    M(){
        memset(t,0,sizeof(t));
    }
    void init(){
        t[0][0]=t[0][2]=t[1][0]=t[2][2]=1;
        t[0][1]=2;
    }
    void E(){
        for(int i=0;i<3;i++){
            t[i][i]=1;
        }
    }
};
M multiply(M a,M b){
    M c;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++){
                c.t[i][j]=(c.t[i][j]+(a.t[i][k]%200907)*(b.t[k][j]%200907))%200907;
            }
        }
    }
    return c;
}
M powM(M a,long k){
    M tem;
    tem.E();
    while(k){
        if(k&1)tem=multiply(a,tem);
        a=multiply(a,a);
        k>>=1;
    }
    return tem;
}
int main(){
    M a,b,c;
    a.t[0][0]=2;
    a.t[1][0]=1;
    a.t[2][0]=1;
    b.init();
    while(cin>>n){
        if(n==0)break;
        if(n<3){
            cout<<a.t[2-n][0]<<endl;
        }
        else {
            c=powM(b,n-2);
            c=multiply(c,a);
            cout<<c.t[0][0]%200907<<endl;
        }
    }
    return 0;
}

posted @ 2014-07-21 13:32  Mr.XuJH  阅读(144)  评论(0编辑  收藏  举报