hdu 6050 funny function

来源:互联网 发布:win7摄像头软件ecap 编辑:程序博客网 时间:2024/05/01 07:22

F1,1=F1,2=1
F1,i=F1,i1+2F1,i2|i>=3
Fi,j=j+N1k=jFi1,k
给定N,M,求Fm,1

首先昨天先写了几个,发现Fi,j=Fi,j1+2Fi,j2也是成立的,于是就有下面的:
Fi,j+1Fi,j=2Fi,j1
Fi,jFi,j1=2Fi,j2

Fi,3Fi,2=2Fi,1
迭加得:
Fi,j+1Fi,2=2j1k=1Fi,k
Fi,j+1Fi,1=Fi,1+Fi,2+...+Fi,j1+A
这里
A=2Fi,2+Fi,3+...+Fi,j1
j+1为奇数时
A=Fi,j

Fi,j+1Fi,1=jk=1Fi,k
j+1为偶数时,
2Fi,j+Fi,j+1=Fi,j+2Fi,j+1+Fi,1Fi,2=k=jk=1Fi,k

n为偶数时
Fi,1=nk=1Fi1,k=Fi1,n+1Fi1,1

[Fi,j+1Fi,j]=[1120][Fi,jFi,j1]

Fi,1=Fi1,1AnB0 A,B0
Fm,1=F1,1(AnB0)m1

同理n为奇数时一样,
Fm,1=F1,1(AnB1)m1
其中,

A=[1120]

n偶数
B=[1001]

n奇数
B=[0121]

#include<cstdio> #include<cstring>#include<iostream>using namespace std;typedef long long ll;const ll P = 1000000007;const int N=2;ll n,m;struct matrix{    ll a[N][N];    int row,col;    matrix():row(N),col(N){memset(a,0,sizeof(a));}    matrix(int x,int y):row(x),col(y){memset(a,0,sizeof(a));}    ll* operator [] (int x){return a[x];}    matrix operator * (matrix x){        matrix tmp ;        for (int i=0;i<=n+1;i++)            for (int j=0;j<=n+1;j++){                tmp[i][j]=0;                for (int k=0;k<=n+1;k++)                    tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j])%P;            }        return tmp;    }       matrix operator - (matrix x){        matrix tmp ;        for (int i=0;i<=n+1;i++)            for (int j=0;j<=n+1;j++){                tmp[i][j]=a[i][j] - x[i][j] + P;                tmp[i][j]%=P;            }        return tmp;    }       void operator *= (matrix x){*this = *this * x;}    matrix operator ^ (ll x){        matrix ret;        for (int i=0;i<=n+1;i++)ret[i][i]=1;        matrix tmp = *this;        for (;x;x>>=1,tmp*=tmp){if(x&1)ret *=tmp;}        return ret;    }};int main(){    long long T,nn,mm;    cin>>T;    n=0;    while(T--){        scanf("%lld%lld",&nn,&mm);        matrix A,B,ans;        A[0][0]=1;A[0][1]=2;A[1][0]=1;A[1][1]=0;        if(nn&1){            B[0][0]=0;B[0][1]=2;            B[1][0]=1;B[1][1]=-1;        } else {            B[0][0]=1;B[0][1]=0;            B[1][0]=0;B[1][1]=1;        }        ans = ((A ^ nn) - B) ^ (mm-1);        cout<<(ans[0][0])<<endl;    }    return 0;}

然后用特征值算矩阵n次方,可以求得
Fm,1=(2n1)m123|n
Fm,1=(2n1)m12+13|n
除三要么用逆元,要么取模的时候先对3000000021取模,最后再对1000000007取模。
于是,

#include <cstdio>#include <cstring>#include <iostream>using namespace std;typedef long long ll;const ll P = 3000000021LL;const ll MOD = 1000000007;ll pow(ll a,ll n){    if(n==0) return 1LL;    ll tmp = pow(a,n/2);    if(n&1)        return tmp*tmp%P*a%P;    return tmp*tmp%P;}int main(){    int T;    ll n,m;    cin>>T;    while(T--){        scanf("%lld%lld",&n,&m);        ll t = pow(2LL,n);        t = (t - 1) % P;        t = pow(t,m-1);        if(n&1) t = t * 2LL + 1;        else t = t * 2LL;        t /= 3LL;        cout<<t%MOD<<endl;    }    return 0;}
原创粉丝点击