`

HDU 2842 Chinese Rings

阅读更多
/*
*  [题意]
*   有n个灯,初始时是全亮的,第一个灯可以按(按下之后改变状态)
*   然后如果前k个灯全灭且第k+1个灯亮,则第k+2个灯可以按
*   问至少要多少步灭掉所有灯?
*  [解题方法](对于n个灯,所求为f[n])
*   1. 要想灭掉最后一个灯,得先灭掉前n-2个灯(第n-1个灯留亮)(f[n-2]+1)
*       {注:灭掉最后一个灯需要1步}
*   2. 要想灭掉第n-1个灯,得先让第n-2个灯变回亮,要第n-2个灯变回亮,得先让第n-3个灯变回亮...
*       即要把前n-2个灯都变回亮(f[n-2])
*   3. 把前n-2个灯变回亮后,就剩下前n-1个灯是亮的,即剩下的任务就是把n-1个灯灭掉(f[n-1])
*   综上所述:f[n] = 2*f[n-2] + f[n-1] + 1
*   所以得矩阵:
*   |1 2 1|     |f[n-1]|        |f[n]  |
*   |1 0 0|  *  |f[n-2]|    =   |f[n-1]|
*   |0 0 1|     |1     |        |1     |
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define LL long long
#define FF(i, n) for(int i = 0; i < n; i++)
#define M 3

int ans[M], mod = 200907;
int ret[M][M];
int init[M][M];
int ss[M][M] = {1, 2, 1,
                1, 0, 0,
                0, 0, 1};

void ini (int n)
{
    FF(i, n) FF(j, n) init[i][j] = ss[i][j];
}

void matmul(int a[][M], int b[][M], int n)
{
    int tp[M][M] = {0};
    FF(i, n) FF(k, n) if(a[i][k]) FF(j, n) if(b[k][j])
        tp[i][j] = (tp[i][j] + (LL)a[i][k]*b[k][j]) % mod;
    FF(i, n) FF(j, n) a[i][j] = tp[i][j];
}

void matmul(int a[], int b[][M], int n)
{
    int tp[M] = {0};
    FF(j, n) if(a[j]) FF(i, n) if(b[i][j])
        tp[i] = (tp[i] + (LL)a[j]*b[i][j]) % mod;
    FF(i, n) a[i] = tp[i];
}

void qmod(int n, int b)
{
    FF(i, n) FF(j, n) ret[i][j] = (i==j);
    for ( ; b; b >>= 1)
    {
        if (b & 1) matmul(ret, init, n);
        matmul(init, init, n);
    }
}

int main()
{
    int n;
    while (cin >> n, n)
    {
        if (n < 3) {
            cout << n << endl;
            continue;
        }
        ini(M);
        ans[0] = 2; ans[1] = ans[2] = 1;
        qmod(M, n-2);
        matmul(ans, ret, M);
        cout << ans[0] << endl;
    }
    return 0;
}

 

1
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics