1. 程式人生 > >2013 ACM/ICPC 長沙賽區湖大全國邀請賽 A題(6.1修訂)

2013 ACM/ICPC 長沙賽區湖大全國邀請賽 A題(6.1修訂)

小記:這次大賽教訓慘重,ACM的路任重道遠,現在努力做出每道題的解題報告吧。以此來撫慰我那慘痛的心靈。

題目:


這個題目名叫So easy!  當初看了 就想A, 現在看來這估計就是個陷阱,數學不好的必被坑。

由於我是用word寫好的,但是裡面的數學符號複製不出來,所以我就用圖片來描述好了。

Solution


遞推求通項公式的特徵根的方法可以看這個:




(之前沒A之前,犯了右乘和左乘的理解錯誤,改過來就差不多了,之前的程式碼提交的錯了,除了左乘和右乘理解錯誤外,還有就是沒有將進行快速冪的矩陣裡的負元素變成正數(通過加M,即要取模的值變成正數,如果有負數的話,進行快速冪是錯的),全改了之後就A了。)(6.1 修改)

在快速冪的時候就進行取模運算,防溢位。

進過轉換之後,我們發現這題純粹就是一道簡單的矩陣快速冪的模板題。頓時覺得數學是門非常深奧的課程,需要不斷的去學習探索。敗在這題之下,確實只能怪自己基礎不扎

實,受教了。模板我的部落格裡有。


這題,經過幾天的思考,在wuzhengkai大神的點撥下,以及另一位神犇(連結沒找到)的幫助下,頓悟了。在此特地感謝!

//下面貼上我的程式碼,湖大OJ 暫時打不開,所以還不知道正確與否,不過根據我自己生成的隨機資料,理論上應該沒錯。

下面是錯誤的程式碼:

#include <iostream>
#include <stdio.h>

using namespace std;

#define N 2
#define ll unsigned long long

struct Matrix {
    ll v[N][N];
};

Matrix A,B={1,0,0,1};
ll M;

Matrix mul(Matrix m1,Matrix m2,ll M){
    int i,j,k;
    Matrix c;
    for(i=0;i<N;i++)for(j=0;j<N;j++){
        c.v[i][j]=0;
        for(k=0;k<N;k++)
            c.v[i][j]+=(m1.v[i][k]*m2.v[k][j])%M;
        c.v[i][j] %= M;
    }
    return c;
}

Matrix Mpow(Matrix A,Matrix B,ll n,ll M){
    Matrix x=A,c=B;
    while(n>=1){
        if(n&1)c=mul(c,x,M);
        n>>=1;
        x=mul(x,x,M);
    }
    return c;
}

int main() {
    //freopen("d:\\in.txt","r",stdin);
    //freopen("d:\\out.txt","w",stdout);
    //int flag = 0;
    ll n, a, b;
    while(cin>>a>>b>>n>>M){
        /*if(flag)cout << endl;
        else flag = 1;*/

        if(n == 1){
            cout << (2*a) % M <<endl;continue;
        }
        if(n == 2){
            cout << (2*a*a + 2*b) % M <<endl;continue;
        }
        A.v[0][0] = 2*a;
        A.v[0][1] = b - a*a ;
        A.v[1][0] = 1;
        A.v[1][1] = 0;
        Matrix p = Mpow(A,B,n-2,M), q = {2*a*a + 2*b, 0, 2*a, 0};
        p = mul(p,q,M);
        cout<<p.v[0][0]<<endl;
    }
    return 0;
}


改正後的A過的程式碼:(6.1修改)

#include <iostream>
#include <stdio.h>

using namespace std;

#define N 2
#define ll long long

struct Matrix {
    ll v[N][N];
};

Matrix A,B={1L,0L,0L,1L};
ll M;

Matrix mul(Matrix m1,Matrix m2,ll M){
    int i,j,k;
    Matrix c;
    for(i = 0; i < N; i++)
        for(j = 0; j < N; j++){
            c.v[i][j] = 0;
            for(k = 0; k < N; k++){
                c.v[i][j] += (m1.v[i][k]*m2.v[k][j])%M;
                c.v[i][j] %= M;
            }
            c.v[i][j] %= M;
    }
    return c;
}

Matrix Mpow(Matrix A,Matrix B,ll n,ll M){
    Matrix x = A,c = B;
    while(n >= 1){
        if(n&1L)c = mul(c,x,M);
        n >>= 1;
        x = mul(x,x,M);
    }
    return c;
}

int main() {
    //freopen("F:\\problem A\\in.txt","r",stdin);
    //freopen("F:\\problem A\\out.txt","w",stdout);
    ll n, a, b, t;
    while(cin>>a>>b>>n>>M){
        if(n == 1){
            cout << (2*(a%M)) % M <<endl;continue;
        }
        if(n == 2){
            cout << ((2*((a%M)*(a%M))%M)%M + (2*b)%M) % M <<endl;continue;
        }
        A.v[0][0] = (2*(a%M)) % M;
        t = a;
        t *= a;
        A.v[0][1] = 1;
        t = b - t;
        while(t < 0)t += M;
        A.v[1][0] = t;
        A.v[1][1] = 0;
        Matrix p = Mpow(A,B,n-2,M), q = {((2*((a%M)*(a%M))%M)%M + (2*b)%M) % M, (2*(a%M)) % M, 0L, 0L};
        p = mul(q,p,M);
        cout<<p.v[0][0]<<endl;
    }
    return 0;
}