题目大意:
费塞的宠物猫刚生了一窝小猫,考虑到它们的健康,费塞决定让它们多做锻炼。它已经设计好了一系列动作让它们做,并且让你来监督指导它们,以防万一它们做过量挂掉了,总共有三种动作,形式化描述为:
g i:让第i只猫拿一颗花生
e i:让第i只猫吃掉它手里的所有花生
s i j:让第i只猫和第j只猫交换手里的花生
费塞会给出一些上述动作(数量固定),然后重复着一些列动作若干次。
先有多个测例,每个测例中将会有n只猫(1 ≤ n ≤ 100,编号为1 - n,测例以n为0结束),重复次数m(0 ≤ m ≤ 1,000,000,000),以及每次重复系列动作的数量k(1 ≤ k ≤ 100),现求出每个测例中,重复完所有动作后每只猫咪手里还有多少花生。
注释代码:
/*
* Problem ID : POJ 3735 Training little cats
* Author : Lirx.t.Una
* Language : C
* Run Time : 110 ms
* Run Memory : 416 KB
*/
#include <string.h>
#include <stdio.h>
//maximum number of cats
//猫咪的最大数量,由于转移矩阵的宽度比猫咪数量大1
//因此下标得取到100 + 1
#define MAXCATN 102
typedef long long llg;
//body of main matrix,主矩阵
//存放原始系列操作的结果
llg b[MAXCATN][MAXCATN];
//answer matrix,存放快速幂结果的矩阵
llg a[MAXCATN][MAXCATN];
//temporary matrix,存放中间结果的矩阵
llg t[MAXCATN][MAXCATN];
int ms;//matrix size,矩阵的宽度(猫咪数量加1)
void
mul( llg (*m1)[MAXCATN], llg (*m2)[MAXCATN] ) {//multiply
//矩阵相乘,结果存放在第一个矩阵中,这样可以避免返回值
//传递时的大量复制工作以及创建矩阵时的重新分配空间的时间
//matrix1,matrix2
int i, j, k;//计数变量
memset(t, 0, sizeof(t));//利用t存放相乘结果
for ( i = 1; i <= ms; i++ )
for ( k = 1; k <= ms; k++ )
if ( m1[i][k] )//重要的剪枝,否则会TLE
for ( j = 1; j <= ms; j++ )
t[i][j] += m1[i][k] * m2[k][j];
memcpy(m1, t, sizeof(t));//将结果覆盖至第一个矩阵
}
void
fstxp( llg (*m)[MAXCATN], llg n ) {//fast exponentiation
//矩阵快速幂,算法和乘方取模运算相同,都采用二分法
int i;
memset(a, 0, sizeof(a));
for ( i = 1; i <= ms; i++ )
a[i][i] = 1LL;//先将answer初始化为单位矩阵
while ( n ) {
if ( n & 1 )
mul( a, m );
mul( m, m );
n >>= 1;
}
}
int
main() {
int n, m, k;//猫咪数量,重复次数,每次循环操作数
char cmd;
int x, y;
int i;
llg swp;//swap,作为交换元
while ( scanf("%d%d%d", &n, &m, &k), n ) {
ms = n + 1;
memset(b, 0, sizeof(b));
for ( i = 1; i <= ms; i++ )
b[i][i] = 1LL;//先将主矩阵初始化为单位矩阵
//最后一行作为猫咪花生的记录行
while ( k-- ) {
scanf("\n%c", &cmd);
switch ( cmd ) {
case 'g' ://加1只作用于最后一行
scanf("%d", &x);
b[ms][x]++;
break;
case 'e' ://清零作用于每一行
scanf("%d", &x);
for ( i = 1; i <= ms; i++ )
b[i][x] = 0LL;
break;
default ://交换作用于每一行
scanf("%d%d", &x, &y);
for ( i = 1; i <= ms; i++ ) {
swp = b[i][x];
b[i][x] = b[i][y];
b[i][y] = swp;
}
break;
}
}
fstxp( b, m );
for ( i = 1; i <= n; i++ )
printf("%lld ", a[ms][i]);
putchar('\n');
}
return 0;
}
无注释代码:
#include <string.h>
#include <stdio.h>
#define MAXCATN 102
typedef long long llg;
llg b[MAXCATN][MAXCATN];
llg a[MAXCATN][MAXCATN];
llg t[MAXCATN][MAXCATN];
int ms;
void
mul( llg (*m1)[MAXCATN], llg (*m2)[MAXCATN] ) {
int i, j, k;
memset(t, 0, sizeof(t));
for ( i = 1; i <= ms; i++ )
for ( k = 1; k <= ms; k++ )
if ( m1[i][k] )
for ( j = 1; j <= ms; j++ )
t[i][j] += m1[i][k] * m2[k][j];
memcpy(m1, t, sizeof(t));
}
void
fstxp( llg (*m)[MAXCATN], llg n ) {
int i;
memset(a, 0, sizeof(a));
for ( i = 1; i <= ms; i++ )
a[i][i] = 1LL;
while ( n ) {
if ( n & 1 )
mul( a, m );
mul( m, m );
n >>= 1;
}
}
int
main() {
int n, m, k;
char cmd;
int x, y;
int i;
llg swp;
while ( scanf("%d%d%d", &n, &m, &k), n ) {
ms = n + 1;
memset(b, 0, sizeof(b));
for ( i = 1; i <= ms; i++ )
b[i][i] = 1LL;
while ( k-- ) {
scanf("\n%c", &cmd);
switch ( cmd ) {
case 'g' :
scanf("%d", &x);
b[ms][x]++;
break;
case 'e' :
scanf("%d", &x);
for ( i = 1; i <= ms; i++ )
b[i][x] = 0LL;
break;
default :
scanf("%d%d", &x, &y);
for ( i = 1; i <= ms; i++ ) {
swp = b[i][x];
b[i][x] = b[i][y];
b[i][y] = swp;
}
break;
}
}
fstxp( b, m );
for ( i = 1; i <= n; i++ )
printf("%lld ", a[ms][i]);
putchar('\n');
}
return 0;
}
单词解释:
Facer:人名,费塞
pet:n, 宠物
give birth to:vt, 生孩子
a brood of:一窝,一伙
supervise:vt, 监督,指导
peanut:n, 花生
perform:vt, 执行,完成,表演
come up with:vt, 提出,想出
embarrassing:adj, 令人尴尬的
quantity:n, 量,数量