1.题面
http://poj.org/problem?id=3735
2.题意
有n只小猫,给定关于这n只小猫的三种操作,以及由这k中操作组成的一个序列,将该序列代表的操作执行m次,m的量级为10的9次方,输出最后小猫的状态。
3.思路
将所有操作合并成一个操作矩阵,最后对该矩阵进行m次乘法,使用矩阵快速幂加速运算
4.代码
/***************************************************************** > File Name: cpp_acm.cpp > Author: Uncle_Sugar > Mail: [email protected] > Created Time: Fri 07 Oct 2016 14:29:37 CST *****************************************************************/ # include <cstdio> # include <cstring> # include <cctype> # include <cmath> # include <cstdlib> # include <climits> # include <iostream> # include <iomanip> # include <set> # include <map> # include <vector> # include <stack> # include <queue> # include <algorithm> using namespace std; # define rep(i,a,b) for (i=a;i<=b;i++) # define rrep(i,a,b) for (i=b;i>=a;i--) # define mset(aim, val) memset(aim, val, sizeof(aim)) struct QuickIO{ QuickIO(){const int SZ = 1<<20; setvbuf(stdin ,new char[SZ],_IOFBF,SZ); setvbuf(stdout,new char[SZ],_IOFBF,SZ); } //*From programcaicai*// }QIO; template<class T>void PrintArray(T* first,T* last,char delim=' '){ for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim); } /* 1.see the size of the input data before you select your algorithm 2.cin&cout is not recommended in ACM/ICPC 3.pay attention to the size you defined, for instance the size of edge is double the size of vertex */ const int debug = 1; //# const int size = 10 + ; const int INF = INT_MAX>>1; typedef long long ll; const int MatrixSize = 10 + 100; //矩阵大小,注意能小就小 struct Matrix{ ll T[MatrixSize][MatrixSize], sz; //# Matrix(){} Matrix(int _sz){ init(_sz); } void init(int _sz){ sz = _sz; memset(T, 0, sizeof(T)); } void Diag(int v){ for (int i = 1; i <= sz; i++){ T[i][i] = v; } } Matrix operator * (const Matrix& oper)const{ Matrix ret(sz); for (int i = 1; i <= sz; i++){ for (int j = 1; j <= sz; j++){ if (T[i][j] == 0) continue; for(int k = 1; k <= sz; k++){ if (oper.T[j][k] == 0) continue; ret.T[i][k] += T[i][j]*oper.T[j][k]; } } } return ret; } Matrix QuickPowerMod(ll b){ Matrix ret(sz); Matrix t = *this; ret.Diag(1); while (b){ if(b&1) ret = t*ret; t = t*t; b >>= 1; } return ret; } Matrix operator ^ (int n){ Matrix ret(sz); ret.Diag(1); Matrix t = *this; while (n){ if (n & 1) ret = t*ret; t = t*t; n >>= 1; } return ret; } void Print(){ for (int i = 1; i <= sz; i++) PrintArray(T[i] + 1, T[i] + sz + 1); cout << "end" << endl; } }; int main() { /*std::ios::sync_with_stdio(false);cin.tie(0);*/ int n, m, k; while (scanf("%d%d%d", &n, &m, &k) != EOF){ if (n==0 && m==0 && k==0) break; Matrix op(n+1); op.Diag(1); while (k--){ char str[10]; scanf("%s", str); if (str[0] == 'g'){ int a; scanf("%d", &a); ++a; op.T[1][a]++; }else if (str[0] == 's'){ int a, b; scanf("%d%d", &a, &b); ++a, ++b; for (int i = 1; i <= op.sz; i++) swap(op.T[i][a], op.T[i][b]); }else if (str[0] == 'e'){ int a; scanf("%d", &a); a++; for (int i = 1; i <= op.sz; i++) op.T[i][a] = 0; } } //# op.Print(); op = op^m; for (int i = 2; i <= n+1; i++){ printf("%lld%c", op.T[1][i], i==n+1?'\n':' '); } } return 0; }