uva 12045 (矩阵快速幂)

来源:互联网 发布:erp系统java项目 编辑:程序博客网 时间:2024/06/05 17:29

题意:

一个长度为正数的字符串,只包含“a"和"b"两种字符。

每次操作,把所有的b变成ab,a变成b。

如S(1) = ab, 则S(2)=b(ab) =bab 

       记L(n)为第n个串的长度。

      给出L(n) = X , L(m) = Y, L(k)


做法:

设S(n)中字符a、b的个数分别为a(n)、b(n),则L(n)= a(n) + b(n)

很明显有 a(n+1)=b(n),b(n+1) = a(n)+b(n)

即满足斐波那契数列的性质。

于是可以通过构造转移矩阵,利用快速幂,来得到任意两项之间的关系。

不妨设n < m,假设得到的矩阵为

 |a b|

 |c d|

则有 a * a(n) + b * b(n) = a(m)

c * a(n) + d * b(n) = b(m)

a(n) + b(n) = L(n) = X

a(m) + b(m) = L(m) = Y

于是可解出a(n), b(n) ,若小于0 说明字符个数小于0,明显不合题意。

类似可算出a(1),b(1),同样必须保证大于等于0

最后再推出k的情况即可。


#include <cstdio>#include <iostream>using namespace std;const int MOD = 1000000007, INF = 1e9;typedef long long ll;const int N = 2;struct Mat {    ll mat[N][N];    void init() {        for(int i = 0; i < N; i++)            for(int j = 0; j < N; j++)                mat[i][j] = i || j ? 1 : 0;    }    void init2(int x) {        for(int i = 0; i < N; i++)            for(int j = 0; j < N; j++)                mat[i][j] = i == j ? x : 0;    }    Mat operator * (const Mat &ano) {        Mat res;        res.init2(0);        for(int i = 0; i < N; i++)            for(int j = 0; j < N; j++)                for(int k = 0; k < N; k++) {                    res.mat[i][j] += mat[i][k] * ano.mat[k][j];                    res.mat[i][j] %= MOD;                }        return res;    }};Mat quickPow(Mat A, int n) {    Mat res;    res.init2(1);    while(n) {        if(n & 1)            res = res * A;        A = A * A;        n >>= 1;    }    return res;}// a * x + b * y = s1// c * x + d * y = s2void fun(ll a, ll b, ll s1,         ll c, ll d, ll s2, ll &x, ll &y) {    x = y = -1;    if(b * c != d * a) {        y = (a * s2 - c * s1) / (a * d - b * c);        if(a)            x = (s1 - b * y) / a;        else if(c)            x = (s2 - d * y) / c;        if(a * x + b * y != s1 ||           c * x + d * y != s2)           x = y = -1;    }}int main() {//    freopen("in.txt", "r", stdin);    int t, n, x, m, y, k;    ll ans;    Mat A;    scanf("%d", &t);    while(t--) {        scanf("%d%d%d%d%d", &n, &x, &m, &y, &k);        if(n > m) {            swap(n, m);            swap(x, y);        }        ll an, bn;        A.init();        A = quickPow(A, m - n);        fun(1, 1, x, A.mat[0][0] + A.mat[1][0],            A.mat[0][1] + A.mat[1][1], y, an, bn);        if(an < 0 || bn < 0) {            puts("Impossible");            continue;        }        ll a1, b1;        A.init();        A = quickPow(A, n-1);        fun(A.mat[0][0], A.mat[0][1], an,            A.mat[1][0], A.mat[1][1], bn,            a1, b1);        if(a1 < 0 || b1 < 0){            puts("Impossible");            continue;        }        A.init();        ll ak, bk;        if(k >= n) {            A = quickPow(A, k - n);            ak = an * ((A.mat[0][0] + A.mat[1][0]) % MOD);            bk = bn * ((A.mat[0][1] + A.mat[1][1]) % MOD);            ak %= MOD, bk %= MOD;            ans = ak + bk;        } else {            A = quickPow(A, n - k);            fun(A.mat[0][0], A.mat[0][1], an,                A.mat[1][0], A.mat[1][1], bn,                ak, bk);            if(ak < 0 || bk < 0) {                puts("Impossible");                continue;            }            ak %= MOD, bk %= MOD;            ans = ak + bk;        }        ans %= MOD;        printf("%d\n", (int)ans);    }    return 0;}

0 0
原创粉丝点击