Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 8468 | Accepted: 2033 |
Description
Facer's pet cat just gave birth to a brood of little cats. Having considered the health of those lovely cats, Facer decides to make the cats to do some exercises. Facer has well designed a set of moves for his cats. He is now asking you to supervise the cats to do his exercises. Facer's great exercise for cats contains three different moves:
g i : Let the ith cat take a peanut.
e i : Let the ith cat eat all peanuts it have.
s i j : Let the ith cat and jth cat exchange their peanuts.
All the cats perform a sequence of these moves and must repeat it m times! Poor cats! Only Facer can come up with such embarrassing idea.
You have to determine the final number of peanuts each cat have, and directly give them the exact quantity in order to save them.
Input
The input file consists of multiple test cases, ending with three zeroes "0 0 0". For each test case, three integers n, m and k are given firstly, where n is the number of cats and k is the length of the move sequence. The following k lines describe the sequence.
(m≤1,000,000,000, n≤100, k≤100)
Output
For each test case, output n numbers in a single line, representing the numbers of peanuts the cats have.
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
Source
题型:数论
题意:
对n只猫进行操作,起始时所有猫都没有花生,操作有如下几种:
1、g i :给第i个猫一个花生
2、e i :让第i个猫吃掉它所有的花生
3、s i j :让第i个猫和第j个猫交换它们的花生
现在对猫有m轮操作,每轮有k个指令,问最后每个猫各有多少花生。
分析:
解题的关键就是构造出一轮操作的矩阵。
设置花生的矩阵为行矩阵(0 0 0 …… 0 0 1)总共n+1个元素。
构造一轮操作的矩阵:
先初始化一个(n+1 * n+1)的单位矩阵;
有g i时,第i列的最后一位加1;
有e i时,第i列的元素全部设置为0;
有s i j时,将第i列与第j列对调。
以样例为例:
初始化矩阵:p(0 0 0 1)
即每只猫咪的花生米个数为0。
初始化a为单位矩阵
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
经过一轮操作
g 1 //给1号1颗花生米,在第一列的最后一行加1
1 0 0 0
0 1 0 0
0 0 1 0
1 0 0 1
g 2
1 0 0 0
0 1 0 0
0 0 1 0
1 1 0 1
g 2
1 0 0 0
0 1 0 0
0 0 1 0
1 2 0 1
s 1 2 //交换第1,2列
0 1 0 0
1 0 0 0
0 0 1 0
2 1 0 1
g 3
0 1 0 0
1 0 0 0
0 0 1 0
2 1 1 1
e 2 //将第2列全部置为0
0 0 0 0
1 0 0 0
0 0 1 0
2 0 1 1
最后:
p = p * a* a* a …… * a* a = p * (a ^ m)
使用矩阵快速幂即可解决。
注意在矩阵乘法中加一个优化,否则TLE(坑爹了,说多了都是泪啊~)。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL __int64
using namespace std;
const LL MAXN=110;
struct Matrix{
LL mat[MAXN][MAXN];
};
LL n,m,k;
Matrix mull(Matrix m1,Matrix m2){
Matrix ans;
memset(ans.mat,0,sizeof(ans.mat));
for(LL j=0;j<=n;j++)
for(LL k=0;k<=n;k++)
if(m1.mat[0][k]&&m2.mat[k][j])//优化,否则TLE
ans.mat[0][j]=(ans.mat[0][j]+m1.mat[0][k]*m2.mat[k][j]);
return ans;
}
Matrix mul(Matrix m1,Matrix m2){
Matrix ans;
memset(ans.mat,0,sizeof(ans.mat));
for(LL i=0;i<=n;i++)
for(LL j=0;j<=n;j++)
for(LL k=0;k<=n;k++)
if(m1.mat[i][k]&&m2.mat[k][j])//优化,否则TLE
ans.mat[i][j]=(ans.mat[i][j]+m1.mat[i][k]*m2.mat[k][j]);
return ans;
}
Matrix pow(Matrix m1,LL b){
Matrix ans;
for(LL i=0;i<=n;i++)
for(LL j=0;j<=n;j++)
ans.mat[i][j]=(i==j?1:0);
while(b){
if(b&1)
ans=mul(ans,m1);
m1=mul(m1,m1);
b/=2;
}
return ans;
}
int main(){
Matrix a,p;
while(1){
scanf("%I64d%I64d%I64d",&n,&m,&k);
if(n==0&&m==0&&k==0) break;
for(LL i=0;i<=n;i++){
for(LL j=0;j<=n;j++){
if(i==j){
a.mat[i][j]=1;
//p.mat[i][j]=1;
}
else{
a.mat[i][j]=0;
//p.mat[i][j]=0;
}
}
}
for(LL i=0;i<n;i++){
p.mat[0][i]=0;
}
p.mat[0][n]=1;
char str[5];
LL x,y;
while(k--){
scanf("%s",str);
if(str[0]=='g'){
scanf("%I64d",&x);
a.mat[n][x-1]++;
}
if(str[0]=='e'){
scanf("%I64d",&x);
for(LL j=0;j<=n;j++){
a.mat[j][x-1]=0;
}
}
if(str[0]=='s'){
scanf("%I64d%I64d",&x,&y);
for(LL j=0;j<=n;j++){
LL tmp=a.mat[j][x-1];
a.mat[j][x-1]=a.mat[j][y-1];
a.mat[j][y-1]=tmp;
}
}
}
Matrix ans=pow(a,m);
p=mull(p,ans);
printf("%I64d",p.mat[0][0]);
for(int i=1;i<n;i++){
printf(" %I64d",p.mat[0][i]);
}
printf("\n");
}
return 0;
}