首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

POJ 3735 Training little cats 矩阵2分幂 + 矩阵优化

2012-09-18 
POJ3735Training little cats矩阵二分幂 + 矩阵优化来源:http://poj.org/problem?id3735题意:有一些猫,这

POJ 3735 Training little cats 矩阵二分幂 + 矩阵优化

来源:http://poj.org/problem?id=3735

题意:有一些猫,这些猫可以获得一些花生,有三种操作:某只猫可以获得一个花生;某只猫花生变为0;两只猫的花生数目交换。问经过k次交换,且k次交换循环m次之后,每只猫有多少花生。

思路:因为猫的数量不多(<= 100),所以,可以用矩阵做,每种操作对应一个矩阵,矩阵相乘即可。循环m次即是矩阵的m次方,可以用矩阵二分幂。还有就是矩阵 乘法的优化,只有这样才可过。

矩阵乘法优化:

#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);elsemult2(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;}


热点排行