• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

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

 

posted @ 2013-04-23 02:36  LyonLys  阅读(289)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3