POJ 3735 Training little cats

题目大意:

        费塞的宠物猫刚生了一窝小猫,考虑到它们的健康,费塞决定让它们多做锻炼。它已经设计好了一系列动作让它们做,并且让你来监督指导它们,以防万一它们做过量挂掉了,总共有三种动作,形式化描述为:

                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, 量,数量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值