zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    C#使用结构体,输入5个人的学号,姓名,分数,按照成绩高低排列打印出来
    数据库考试试题
    数据库存储系统应用,超市小票系统
    数据库变量与语句
    练习:C#---类(身份证号截取生日、验证邮箱、DateTime)
    Chapter 3. 类---String类、Math类、Datetime类
    练习:C#---for循环(整数和、阶乘、楼梯)
    Chapter 2 C#语句---异常语句
    Chapter 2. C#语句---循环语句
    Chapter 2 C#语句---选择语句
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_3735_Lyon.html
Copyright © 2011-2022 走看看