• LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)


    Jan's LightOJ :: Problem 1052 - String Growth

    uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3196

      很好的一题,也是我的队友xdp给我的题。

      题意是根据字符串的变化规律,给出第n次和第m次变化的时候的长度,求出第k次变化时的长度。

      开始的时候感觉这是难题,不过仔细想了一下,发现只需要高斯消元(其实在我这里只是一个简单的解二元一次方程组罢了。。囧)解出起始的时候a和b的个数,然后套上矩阵快速幂就可以得到第k项了。这题搞了整整一天,WA的地方居然是一个int没有改成LL。开始的时候,以为高斯消元做除法的过程中不会溢出,结果不知道为什么的,被我搞了好多数据之后,发现了一个会导致溢出的数据,改过来之后就过了!

    代码如下:

    View Code
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <vector>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 
      9 #define REP(i, n) for (int i = 0; i < (n); i++)
     10 #define REP_1(i, n) for (int i = 1; i <= (n); i++)
     11 
     12 typedef long long LL;
     13 
     14 LL fab[60];
     15 void preFab() {
     16     fab[0] = 0ll;
     17     fab[1] = 1ll;
     18     REP_1(i, 58) {
     19         fab[i + 1] = fab[i] + fab[i - 1];
     20 //        cout << i + 1 << ' ' << fab[i + 1] << endl;
     21     }
     22 }
     23 
     24 LL mat[2][3];
     25 
     26 void swapRow() {
     27     REP(i, 3) swap(mat[0][i], mat[1][i]);
     28 }
     29 
     30 bool test(int n, LL x, int m, LL y, int &a, int &b) {
     31     if (n > 50 || m > 50) return false;
     32     if (fab[n - 1] > x) return false;
     33     if (fab[m - 1] > y) return false;
     34     REP(i, 2) {
     35         mat[0][i] = fab[n + i];
     36         mat[1][i] = fab[m + i];
     37     }
     38     mat[0][2] = x;
     39     mat[1][2] = y;
     40     while (true) {
     41         if (mat[0][0] > mat[1][0]) swapRow();
     42         if (mat[0][0]) {
     43             LL tmp = mat[1][0] / mat[0][0];
     44             REP(i, 3) mat[1][i] -= tmp * mat[0][i];
     45         } else {
     46             break;
     47         }
     48     }
     49     swapRow();
     50 //    REP(i, 2) {
     51 //        REP(j, 3) {
     52 //            cout << mat[i][j] << ' ';
     53 //        }
     54 //        cout << endl;
     55 //    }
     56 
     57     LL ans[2];
     58     for (int i = 1; i >= 0; i--) {
     59         if (mat[i][i]) {
     60             if (mat[i][2] % mat[i][i]) return false;
     61             ans[i] = mat[i][2] / mat[i][i];
     62             if (ans[i] < 0) return false;
     63             for (int j = i - 1; j >= 0; j--) {
     64                 mat[j][2] -= mat[j][i] * ans[i];
     65                 mat[j][i] = 0ll;
     66             }
     67         } else {
     68             if (mat[i][2]) return false;
     69             ans[i] = 0ll;
     70         }
     71     }
     72     a = ans[0], b = ans[1];
     73 
     74 //    REP(i, 2) {
     75 //        REP(j, 3) {
     76 //            cout << mat[i][j] << ' ';
     77 //        }
     78 //        cout << endl;
     79 //    }
     80 //    cout << a << "~~" << b << endl;
     81     return true;
     82 }
     83 
     84 const int matSize = 2;
     85 const LL mod = 1000000007;
     86 struct Mat {
     87     LL val[matSize][matSize];
     88     Mat(LL one = 0ll) {
     89         REP(i, matSize) {
     90             REP(j, matSize) {
     91                 val[i][j] = 0ll;
     92             }
     93             val[i][i] = one;
     94         }
     95     }
     96     void print() {
     97         REP(i, 2) {
     98             REP(j, 2) {
     99                 cout << val[i][j] << ' ';
    100             }
    101             cout << endl;
    102         }
    103         cout << "~~~" << endl;
    104     }
    105 } ;
    106 
    107 Mat operator * (Mat &a, Mat &b) {
    108     Mat ret = Mat();
    109     REP(i, matSize) {
    110         REP(k, matSize) {
    111             REP(j, matSize) {
    112                 ret.val[i][j] += a.val[i][k] * b.val[k][j] % mod;
    113             }
    114         }
    115     }
    116     return ret;
    117 }
    118 
    119 Mat operator ^ (Mat &a, int p) {
    120     Mat ret = Mat(1);
    121     Mat _a = a;
    122     while (p > 0) {
    123         if (p & 1) {
    124             ret = ret * _a;
    125         }
    126         _a = _a * _a;
    127         p >>= 1;
    128     }
    129     return ret;
    130 }
    131 
    132 LL work(int k, int a, int b) {
    133     Mat Base = Mat();
    134     Mat op = Mat();
    135     op.val[0][1] = op.val[1][0] = op.val[1][1] = 1ll;
    136     Base.val[0][0] = (LL) a;
    137     Base.val[0][1] = (LL) b;
    138     op = op ^ (k - 1);
    139 //    op.print();
    140     Base = Base * op;
    141 //    Base.print();
    142     return (Base.val[0][0] + Base.val[0][1]) % mod;
    143 }
    144 
    145 LL bruceForce(int k, int a, int b) {
    146     LL na = (LL) a, nb = (LL) b;
    147     REP(i, k - 1) {
    148         nb += na;
    149         na = nb - na;
    150         nb %= mod;
    151     }
    152     return (na + nb) % mod;
    153 }
    154 
    155 int main() {
    156 //    freopen("in", "r", stdin);
    157     preFab();
    158     int n, m, k, na, nb, T;
    159     LL x, y;
    160     cin >> T;
    161     REP_1(cas, T) {
    162         cin >> n >> x >> m >> y >> k;
    163         printf("Case %d: ", cas);
    164         if (test(n, x, m, y, na, nb)) {
    165 //            cout << na << ' ' << nb << endl;
    166             cout << work(k, na, nb) << endl;
    167 //            cout << "~~~~~~~~ " << bruceForce(k, na, nb) << endl;
    168         } else {
    169             puts("Impossible");
    170         }
    171     }
    172     return 0;
    173 }

    测试数据是:

    Sample in:

    4
    1 1 2 1 10
    7 277 8 448 1
    39 842831057 38 321932817 1 (错在这个数据了)
    1 1003 7 16343 9000000

    Sample out:

    Case 1: 55
    Case 2: 17
    Case 3: Impossible
    Case 4: 147991426

    ——written by Lyon

  • 相关阅读:
    Eureka的工作原理以及它与ZooKeeper的区别
    利用javascript判断文件是否存在
    带jsk证书,请求https接口
    C# .net 数组倒序排序
    C#中ArrayList和string,string[]数组的转换
    C#中遍历ArrayList的三种方法
    求其中同一个主叫号码的两次通话之间间隔大于10秒的通话记录ID
    启动tomcat时,一直卡在Deploying web application directory这块的解决方案
    Linux下修改Mysql的用(root的密码及修改root登录权限
    启动MySql提示:The server quit without updating PID file(…)失败
  • 原文地址:https://www.cnblogs.com/LyonLys/p/LOJ_1052_uva_12045_Lyon.html
Copyright © 2020-2023  润新知