POJ 3735 Training little cats(矩阵快速幂)
2015-09-02 13:02
423 查看
Description
有n只猫,开始时每只猫都没有花生,三种操作
g x:给第x只猫一个花生
e x:第x只猫把它所拥有的花生都吃完
s x y:第x只猫与第y只猫交换所拥有的所有花生
现在给出k中操作以及循环数m,问在进行了m次这k次操作后每只猫分别有多少个花生
Input
多组输入u,每组用例第一行为三个整数n,m,k分别表示猫数,操作循环数以及操作数,之后k行每行一个操作,以0 0 0结束输入
Output
对于每组用例,输出m轮k次操作后每只猫所拥有的花生数
Sample Input
3 1 6
g 1
g 2
g 2
s 1 2
g 3
e 2
0 0 0
Sample Output
2 0 1
Solution
将每只猫的花生数放在一个1*n的矩阵中,考虑用k次操作构造成一个n*n矩阵A,因为三种操作中存在某种猫的花生数加一的操作,所以要把矩阵扩展一位放1,即[1,cnt1,cnt2,…,cntn],初始化矩阵A为单位矩阵,对于操作1,要把A[0][x]++;对于操作2,要令A[i][x]=0;对于操作3,要swap(A[i][x],A[i][y]),构造出A矩阵之后用矩阵快速幂求出A^m后第一行元素即为操作后每只猫的花生数
Code
有n只猫,开始时每只猫都没有花生,三种操作
g x:给第x只猫一个花生
e x:第x只猫把它所拥有的花生都吃完
s x y:第x只猫与第y只猫交换所拥有的所有花生
现在给出k中操作以及循环数m,问在进行了m次这k次操作后每只猫分别有多少个花生
Input
多组输入u,每组用例第一行为三个整数n,m,k分别表示猫数,操作循环数以及操作数,之后k行每行一个操作,以0 0 0结束输入
Output
对于每组用例,输出m轮k次操作后每只猫所拥有的花生数
Sample Input
3 1 6
g 1
g 2
g 2
s 1 2
g 3
e 2
0 0 0
Sample Output
2 0 1
Solution
将每只猫的花生数放在一个1*n的矩阵中,考虑用k次操作构造成一个n*n矩阵A,因为三种操作中存在某种猫的花生数加一的操作,所以要把矩阵扩展一位放1,即[1,cnt1,cnt2,…,cntn],初始化矩阵A为单位矩阵,对于操作1,要把A[0][x]++;对于操作2,要令A[i][x]=0;对于操作3,要swap(A[i][x],A[i][y]),构造出A矩阵之后用矩阵快速幂求出A^m后第一行元素即为操作后每只猫的花生数
Code
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 111 typedef long long ll; struct Mat { ll mat[maxn][maxn];//矩阵 ll row,col;//矩阵行列数 }; Mat mod_mul(Mat a,Mat b)//矩阵乘法 { Mat ans; ans.row=a.row; ans.col=b.col; memset(ans.mat,0,sizeof(ans.mat)); for(ll i=0;i<ans.row;i++) for(ll k=0;k<a.col;k++) if(a.mat[i][k]) for(ll j=0;j<ans.col;j++) ans.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; return ans; } Mat mod_pow(Mat a,ll k)//矩阵快速幂 { Mat ans; ans.row=a.row; ans.col=a.col; for(ll i=0;i<a.row;i++) for(ll j=0;j<a.col;j++) ans.mat[i][j]=(i==j); while(k) { if(k&1)ans=mod_mul(ans,a); a=mod_mul(a,a); k>>=1; } return ans; } int main() { ll n,m,k; while(scanf("%lld%lld%lld",&n,&m,&k),n||m||k) { Mat ans;//初始化一个(n+1)*(n+1)的单位矩阵 ans.row=ans.col=n+1; for(ll i=0;i<ans.row;i++) for(ll j=0;j<ans.col;j++) ans.mat[i][j]=(i==j); while(k--) { char op[3]; ll x,y; scanf("%s",op); if(op[0]=='g') { scanf("%lld",&x); ans.mat[0][x]++; } else if(op[0]=='e') { scanf("%lld",&x); for(ll i=0;i<=n;i++) ans.mat[i][x]=0; } else if(op[0]=='s') { scanf("%lld%lld",&x,&y); for(ll i=0;i<=n;i++) swap(ans.mat[i][x],ans.mat[i][y]); } } ans=mod_pow(ans,m); for(ll i=1;i<=n;i++) printf("%lld%c",ans.mat[0][i],i==n?'\n':' '); } return 0; }
相关文章推荐
- STL学习笔记之traits技术
- Smail 注入遇到的问题以及System.out
- A Presentation of the STL Vector Container
- 判断包含字符String.contains
- UVA 11374 Airport Express (最短路)
- RAID入门一页通,最全的RAID技术、原理图解
- hdu5319 Painter(模拟)
- HDU1239 Calling Extraterrestrial Intelligence Again (打表+暴力)
- [Leetcode]#219 Contains Duplicate II
- [Leetcode]#217 Contains Duplicate
- [Leetcode172]Factorial Trailing Zeroes
- Container With Most Water
- How to Use updateConstraints(什么时候该使用updateConstraints)
- string.contains
- 使用hmailserver搭建邮件服务器
- 使用 mdadm 管理 RAID 阵列
- 有力的技术核心支撑TurboMail邮件系统完美体验
- 设计模式19:Chain Of Responsibility 职责链模式(行为型模式)
- RaidoButton产生的bug
- WinMain