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

poj 3735 Training little cats

http://poj.org/problem?id=3735

  矩阵快速幂的题。表示yy了很长一段时间才想到怎么构造矩阵。。。。不过过了sample以后就1y了!

  简单的说一下构造的方法:一个原始矩阵(代码里面的Base)只用到第一行。前面n个表示的是每只猫拥有的食物,因为刚开始的时候所有猫都是没有食物的,所以全部设置为0。紧接着的n个数表示的是每一个循环里食物数量的改变值。然后就是每个循环的操作,也就是代码里的op矩阵。这个矩阵是这样设置的,初始化的时候,分成四块,其中有三块矩阵是单位矩阵。然后,对于每一个题目要求的操作,食物加一就是Base矩阵后半部分相应位置加一,食物交换就是op矩阵相应的两列交换过来,清空食物就是将op的相应的位置(对应这里的猫拥有的食物的位置)以及将Base中循环里的食物的数量改变值清空。

  可以这样想,现在我们需要的是利用矩阵来简化100个操作的循环,那么要怎样设置矩阵才能实现这样的功能呢?其实将每次循环后每只猫拥有的食物的数量和循环前做对比,可以发现操作后的每个位置的值只是由两部分组成。一部分是上一循环结束后,某一只猫拥有的食物的量,另一部分是循环过后对于这个位置的猫的食物的变化量。于是,处理好操作矩阵,每次就可以用同样的矩阵来模拟循环的操作了。

代码如下:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 typedef __int64 ll;
  8 const int matSize = 200;
  9 int calSize = matSize;
 10 
 11 struct Matrix {
 12     ll val[matSize][matSize];
 13 
 14     Matrix(bool Init = false) {
 15         for (int i = 0; i < calSize; i++) {
 16             for (int j = 0; j < calSize; j++) {
 17                 val[i][j] = 0;
 18             }
 19             if (Init) val[i][i] = 1;
 20         }
 21     }
 22 
 23     void print() {
 24         for (int i = 0; i < calSize; i++) {
 25             for (int j = 0; j < calSize; j++) {
 26                 printf("%I64d ", val[i][j]);
 27             }
 28             puts("");
 29         }
 30         puts("~~~");
 31     }
 32 } Base, op;
 33 
 34 Matrix operator * (Matrix &_a, Matrix &_b) {
 35     Matrix ret = Matrix();
 36 
 37     for (int i = 0; i < calSize; i++) {
 38         for (int k = 0; k < calSize; k++) {
 39             if (_a.val[i][k]) {
 40                 for (int j = 0; j < calSize; j++) {
 41                     ret.val[i][j] += _a.val[i][k] * _b.val[k][j];
 42                 }
 43             }
 44         }
 45     }
 46 
 47     return ret;
 48 }
 49 
 50 Matrix operator ^ (Matrix &_a, ll _p) {
 51     Matrix ret = Matrix(true);
 52 
 53     while (_p) {
 54         if (_p & 1) {
 55             ret = ret * _a;
 56         }
 57         _a = _a * _a;
 58         _p >>= 1;
 59     }
 60 
 61     return ret;
 62 }
 63 
 64 Matrix operator + (Matrix &_a, Matrix &_b) {
 65     for (int i = 0; i < calSize; i++) {
 66         for (int j = 0; j < calSize; j++) {
 67             _a.val[i][j] = _a.val[i][j] + _b.val[i][j];
 68         }
 69     }
 70 
 71     return _a;
 72 }
 73 
 74 void deal(int n, ll m, int k) {
 75     char buf[3];
 76     int a, b;
 77     int pos[101];
 78 
 79     calSize = n << 1;
 80     op = Matrix();
 81     Base = Matrix();
 82     for (int i = 0; i < n; i++) {
 83         pos[i] = i;
 84         op.val[i][i] = op.val[i + n][i] = op.val[i + n][i + n] = 1;
 85     }
 86     while (k--) {
 87         scanf("%s", buf);
 88         switch (buf[0]) {
 89         case 'g':
 90             scanf("%d", &a);
 91             Base.val[0][pos[a - 1] + n]++;
 92             break;
 93         case 'e':
 94             scanf("%d", &a);
 95             Base.val[0][pos[a - 1] + n] = 0;
 96             op.val[pos[a - 1]][a - 1] = 0;
 97             break;
 98         case 's':
 99             scanf("%d%d", &a, &b);
100             swap(pos[a - 1], pos[b - 1]);
101             for (int i = 0, endi = n << 1; i < endi; i++) {
102                 swap(op.val[i][a - 1], op.val[i][b - 1]);
103             }
104             break;
105         }
106     }
107 //    puts("Base");
108 //    Base.print();
109     op = op ^ m;
110 //    puts("op");
111 //    op.print();
112 
113     Matrix ans = Base * op;
114 //    ans.print();
115 
116     for (int i = 0; i < n; i++) {
117         if (i) putchar(' ');
118         printf("%I64d", ans.val[0][i]);
119     }
120     puts("");
121 }
122 
123 int main() {
124     int n, k;
125     ll m;
126 
127     freopen("in", "r", stdin);
128     while (~scanf("%d%I64d%d", &n, &m, &k)&& (n || m || k)) {
129         deal(n, m, k);
130     }
131 
132     return 0;
133 }

 

——written by Lyon

posted @ 2012-09-29 19:58  LyonLys  阅读(261)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3