來源:http://poj.org/problem?id=3735
題意:有一些貓,這些貓可以獲得一些花生,有三種操作:某隻貓可以獲得一個花生;某隻貓花生變爲0;兩隻貓的花生數目交換。問經過k次交換,且k次交換循環m次之後,每隻貓有多少花生。
思路:因爲貓的數量不多(<= 100),所以,可以用矩陣做,每種操作對應一個矩陣,矩陣相乘即可。循環m次即是矩陣的m次方,可以用矩陣二分冪。還有就是矩陣 乘法的優化,只有這樣纔可過。
矩陣乘法優化:
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j){
if(initm[i][j] == 0) continue;
for(int k = 0; k <= n; ++k){
mm[i][k] += initm[i][j] * dd[j][k];
}
}
}
全部代碼:
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long LL;
const int N = 110;
int n,m,k;
LL initm[N][N],addm[N][N],zerom[N][N],exchm[N][N],dd[N][N];
void init(){
memset(initm,0,sizeof(initm));
for(int i = 0; i <= n; ++i){
initm[i][i] = 1;
}
}
void add(int x){
memset(addm,0,sizeof(addm));
for(int i = 0; i <= n; ++i)
addm[i][i] = 1;
addm[n][x-1] = 1;
}
void zero(int x){
memset(zerom,0,sizeof(zerom));
for(int i = 0; i <= n; ++i)
zerom[i][i] = 1;
zerom[x-1][x-1] = 0;
}
void exch(int x,int y){
memset(exchm,0,sizeof(exchm));
for(int i = 0; i <= n; ++i)
exchm[i][i] = 1;
exchm[x-1][x-1] = 0;
exchm[y-1][y-1] = 0;
exchm[y-1][x-1] = 1;
exchm[x-1][y-1] = 1;
}
void mult(LL mm[N][N],LL temp[N][N]){
LL newmm[N][N];
memset(newmm,0,sizeof(newmm));
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j){
if(mm[i][j] == 0) continue;
for(int k = 0; k <= n; ++k){
newmm[i][k] += mm[i][j] * temp[j][k];
}
}
}
memset(mm,0,sizeof(mm));
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j)
mm[i][j] = newmm[i][j];
}
}
void mult2(int x){
LL newmm[N][N];
memset(newmm,0,sizeof(newmm));
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j){
if(initm[i][j] == 0)
continue;
for(int k = 0; k <= n; ++k){
newmm[i][k] += initm[i][j] * initm[j][k];
}
}
}
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j)
initm[i][j] = newmm[i][j];
}
if(x){
LL mm[N][N];
memset(mm,0,sizeof(mm));
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j){
if(initm[i][j] == 0) continue;
for(int k = 0; k <= n; ++k){
mm[i][k] += initm[i][j] * dd[j][k];
}
}
}
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j){
initm[i][j] = mm[i][j];
}
}
}
}
void binary_power(int x){
if(x == 1)
return;
binary_power(x/2);
if(x % 2)
mult2(1);
else
mult2(0);
}
int main(){
//freopen("1.txt","r",stdin);
while(scanf("%d%d%d",&n,&m,&k)){
if(n + m + k == 0)
break;
init();
char ch;
int x,y;
while(k--){
cin >> ch;
if(ch == 'g'){
scanf("%d",&x);
add(x);
mult(initm,addm);
}
else if(ch == 'e'){
scanf("%d",&x);
zero(x);
mult(initm,zerom);
}
else{
scanf("%d%d",&x,&y);
exch(x,y);
mult(initm,exchm);
}
}
for(int i = 0; i <= n; ++i){
for(int j = 0; j <= n; ++j)
dd[i][j] = initm[i][j];
}
if(m == 0){
for(int i = 0; i < n - 1; ++i)
printf("0 ");
printf("0\n");
continue;
}
binary_power(m);
for(int i = 0; i < n - 1; ++i){
printf("%lld ",initm[n][i]);
}
printf("%lld\n",initm[n][n-1]);
}
return 0;
}