【2017.10.27】noip赛前集训 | T1 坐标系【矩乘快速幂优化DP】

T1 坐标系

【题目描述】
从前有个平面直角坐标系。 你每次可以向上、向左或向右走,但不能经过重复的点。 求出你从坐标原点出发,走 n 步有多少种不同的方案。 答案对 109 + 7 取模。


【数据范围】

对于 20% 的数据,n≤10; 对于 40% 的数据,n≤100; 对于 60% 的数据,n≤1000; 对于 80% 的数据,n≤106; 对于 100% 的数据,n≤109。

 

【题解】

虽然学(da)长(lao)们讲了如何推出状态转移方程,但是本蒟蒻还是没有听懂。

于是,让我们打个表:3, 7, 17, 41 ... ...(不是手动打表,先写了个 dfs。当然,dalao也可以手动打表,比如我旁边的wkd学姐)。

于是,我们就发现了一个状态转移方程: f[ i ] = 2 f[i - 1] + f[i - 2]。

然后,你就会发现,裸的DP是只能可以得80分。

可以用矩乘快速幂来优化一下。

初矩阵是 {3, 7}。

因为已经知道了状态转移方程,所以不难推出构造矩阵 { {0, 1}, {1, 2} }。

#include <cstdio>
#define ll long long

const int MOD = 1e9 + 7;

struct Matrix {
    ll a[2][2];
    Matrix () {                                    // 注意矩阵要初始化!!!!!! 
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++) 
                a[i][j] = 0;    
    }
} st, fac;

Matrix operator * (Matrix x, Matrix y) {
    Matrix z;
    for (int i = 0; i < 2; i++) 
        for (int j = 0; j < 2; j++)
            for (int k = 0; k < 2; k++)
                z.a[i][j] += (x.a[i][k] % MOD) * (y.a[k][j] % MOD) % MOD;
    return z;
}

Matrix Fp(Matrix x, ll n) {
    Matrix re;
//    for (int i = 0; i <2; i++) {
//        for (int j = 0; j < 2; j++) 
//            printf("%d ", re.a[i][j]);
//        printf("\n");
//    }
//    printf("\n");    
    
    re.a[0][0] = re.a[1][1] = 1;
    for ( ; n; n >>= 1, x = x * x) {
        if (n & 1) re = re * x;
    }
    return re;
}

ll n;

int main() {
    freopen("coordinate.in", "r", stdin);
    freopen("coordinate.out", "w", stdout);
    
    scanf("%lld", &n);
    
    st.a[0][0] = 3;
    st.a[0][1] = 7;
    
    fac.a[0][0] = 0;
    fac.a[0][1] = 1;
    fac.a[1][0] = 1;
    fac.a[1][1] = 2;
    
    Matrix ans = st * Fp(fac, n - 1);
    
//    for (int i = 0; i <2; i++) {
//        for (int j = 0; j < 2; j++) 
//            printf("%d ", re.a[i][j]);
//        printf("\n");
//    }
//    printf("\n");        
        
    printf("%lld\n", ans.a[0][0] % MOD);                        // 千万别忘了 % ,因为这个我 WA 了一次。 
    return 0;
}
AC

 (再说一遍)千万别忘了给矩阵初始化!!!!!还有取模(有点计算,过程中也要%,不然爆LL就GG了 :-()!!!千万别忘了!!!!!

menci的OJ

posted @ 2017-10-28 21:29  E-Valley  阅读(322)  评论(0)    收藏  举报