POJ3735 Training little cats DP,矩阵快速幂,稀疏矩阵优化

题目大意是,n只猫,有k个动作让它们去完成,并且重复m次,动作主要有三类gi,ei,s i j,分别代表第i只猫获得一个花生,第i只猫吃掉它自己所有的花生,第i只和第j只猫交换彼此的花生。k,n不超过100,m不超过1000,000,000,计算出最后每只猫还剩下多少个花生。

我们假设一个n维向量P,每个分量的值代表这n只猫所拥有的花生数,那么对于gi操作其实就是在第i维分量上加上1;对于ei,那就是在第i维分量上乘以0,说到这里,有木有感觉这很像3D坐标转化中的平移矩阵和缩放矩阵?没错,就是这个意思,现在知道g i 和 e i对应的操作,那么s i j 呢,第i维分量就是第i维分量乘以0加上第j维分量乘以1,第j维分量就是第i行分量乘以1加上第j行分量乘以0。

由于要支持平移操作,我们需要对向量再增加一维,并且一直保持1,转移矩阵也是 (n + 1) * (n + 1),初始时该矩阵为单位矩阵,我们将每一个操作转化成矩阵,再让向量P与其相乘,由于满足结合律,我们可以先让这k个矩阵先相称,然后对结果作m次幂,因为m很大,用快速幂来优化就行,但是到这里直接提交代码的话会TLE,为什么呢。。。还是矩阵相乘复杂度过高了,我们发现这个矩阵大多数元素是0,所以在相乘的时候可以略去很多不需要的乘法,具体优化看代码吧。

#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map>
#include <time.h>
using namespace std;

#define MAXSIZE 101
typedef long long MYTYPE;
MYTYPE States[MAXSIZE][MAXSIZE];

void VectorMulMatrix(MYTYPE v[MAXSIZE], MYTYPE a[][MAXSIZE], MYTYPE res[MAXSIZE])
{
	memset(res, 0, sizeof(MYTYPE)* MAXSIZE);
	for (int i = 0; i < MAXSIZE; i++)
	{
		for (int j = 0; j < MAXSIZE;j++)
		{
			res[i] += (v[j] * a[j][i]);
		}
	}
}

void Product(MYTYPE a[][MAXSIZE], MYTYPE b[][MAXSIZE], MYTYPE res[][MAXSIZE])
{
	memset(res, 0, sizeof(MYTYPE)* MAXSIZE * MAXSIZE);
	for (int i = 0; i < MAXSIZE; i++)
	{
		for (int j = 0; j < MAXSIZE; j++)
		{
			if (a[i][j])
			{
				for (int k = 0; k < MAXSIZE; k++)
				{
					res[i][k] += (a[i][j] * b[j][k]);
				}
			}

		}
	}
}

void QProduct(MYTYPE p[][MAXSIZE], MYTYPE res[][MAXSIZE], int n)
{
	memset(res, 0, sizeof(MYTYPE)* MAXSIZE * MAXSIZE);
	MYTYPE tmp[2][MAXSIZE][MAXSIZE];
	MYTYPE tmpres[MAXSIZE][MAXSIZE];
	memcpy(tmp[0], p, sizeof(MYTYPE)* MAXSIZE * MAXSIZE);
	int i = 0;
	for (int k = 0; k < MAXSIZE; k++)
	{
		res[k][k] = 1;
	}
	while (n)
	{
		if (n & 1)
		{
			memcpy(tmpres, res, sizeof(MYTYPE)* MAXSIZE * MAXSIZE);
			Product(tmpres, tmp[i & 1], res);
		}
		Product(tmp[i & 1], tmp[i & 1], tmp[(i + 1) & 1]);
		i++;
		n = n >> 1;
	}
}

void IdentityMatrix(MYTYPE a[][MAXSIZE])
{
	memset(a, 0, sizeof(MYTYPE)* MAXSIZE * MAXSIZE);
	for (int i = 0; i < MAXSIZE; i++)
	{
		a[i][i] = 1;
	}
}

int main()
{
#ifdef _DEBUG
	freopen("e:\\in.txt", "r", stdin);
#endif
	int n, m, k;
	MYTYPE CurState[MAXSIZE][MAXSIZE];
	MYTYPE tmpState[MAXSIZE][MAXSIZE];
	MYTYPE tmpRes[MAXSIZE];
	MYTYPE cur[MAXSIZE];
	while (scanf("%d %d %d\n", &n, &m, &k) != EOF)
	{
		if (n == 0 && m == 0 && k == 0)
		{
			break;
		}
		memset(cur, 0, sizeof(MYTYPE)* MAXSIZE);
		memset(tmpRes, 0, sizeof(MYTYPE)* MAXSIZE);
		cur[MAXSIZE - 1] = 1;
		char op;
		IdentityMatrix(States);
		for (int i = 0; i < k; i++)
		{
			IdentityMatrix(CurState);
			scanf("%c", &op);
			if (op == 'g')
			{
				int value;
				scanf("%d\n", &value);
				CurState[MAXSIZE - 1][value - 1] = 1;
			}
			else if (op == 'e')
			{
				int value;
				scanf("%d\n", &value);
				CurState[value - 1][value - 1] = 0;
				CurState[MAXSIZE - 1][value - 1] = 0;
			}
			else
			{
				int value1, value2;
				scanf("%d %d\n", &value1, &value2);
				CurState[value1 - 1][value1 - 1] = 0;
				CurState[value2 - 1][value2 - 1] = 0;
				CurState[value2 - 1][value1 - 1] = 1;
				CurState[value1 - 1][value2 - 1] = 1;
			}
			Product(States, CurState, tmpState);
			memcpy(States, tmpState, sizeof(MYTYPE)* MAXSIZE * MAXSIZE);
		}
		if (m != 0)
		{
			QProduct(States, tmpState, m);
			VectorMulMatrix(cur, tmpState, tmpRes);
		}

		for (int i = 0; i < n; i++)
		{
			printf("%I64d ", tmpRes[i]);
		}
		printf("\n");
	}
	return 0;
}

POJ3735 Training little cats DP,矩阵快速幂,稀疏矩阵优化,布布扣,bubuko.com

时间: 2024-12-18 14:05:43

POJ3735 Training little cats DP,矩阵快速幂,稀疏矩阵优化的相关文章

TZOJ--5480: 孤衾易暖 // POJ--3735 Training little cats (矩阵快速幂)

5480: 孤衾易暖 时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte 描述 哇,好难,我要放弃了(扶我起来,我还能A 寒夜纵长,孤衾易暖,钟鼓渐清圆. 生活也许有些不如意的地方,但是没有什么是拥有一只猫不能解决的,我最喜欢苏格兰折耳猫. 现在我有n只小猫,我要训练这些猫去满足我奇奇怪怪的需求. 就是要让他们去得到鱼,这样他们才会快乐.刚开始他们是没有鱼的 我对这些猫有3种训练要求: 第一种要求为get x,意为让第x只猫咪得到一条: 第二种要求为e

poj 3735 Training little cats(矩阵快速幂)

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 t

poj 3735 Training little cats (矩阵快速幂)

题目链接: http://poj.org/problem?id=3735 题意: 有n只猫咪,开始时每只猫咪有花生0颗,现有一组操作,由下面三个中的k个操作组成:               1. g i 给i只猫咪一颗花生米               2. e i 让第i只猫咪吃掉它拥有的所有花生米               3. s i j 将猫咪i与猫咪j的拥有的花生米交换 现将上述一组操作做m次后,问每只猫咪有多少颗花生? 思路: http://www.cnblogs.com/acS

HDU 2294 Pendant (DP+矩阵快速幂降维)

HDU 2294 Pendant (DP+矩阵快速幂降维) ACM 题目地址:HDU 2294 Pendant 题意: 土豪给妹子做首饰,他有K种珍珠,每种N个,为了炫富,他每种珍珠都要用上.问他能做几种长度[1,N]的首饰. 分析: 1 ≤ N ≤ 1,000,000,000简直可怕. 首先想dp,很明显可以想到: dp[i][j] = (k-(j-1))*dp[i-1][j-1] + j*dp[i-1][j](dp[i][j]表示长度为i的并且有j种珍珠的垂饰有多少个) 然后遇到N太大的话,

POJ3420 Quad Tiling DP + 矩阵快速幂

题目大意是用1*2的骨牌堆积成4*N的矩形,一共有多少种方法,N不超过10^9. 这题和曾经在庞果网上做过的一道木块砌墙几乎一样.因为骨牌我们可以横着放,竖着放,我们假设以4为列,N为行这样去看,并且在骨牌覆盖的位置上置1,所以一共最多有16种状态.我们在第M行放骨牌的时候,第M+1行的状态也是有可能被改变的,设S(i,j)表示某一行状态为i时,将其铺满后下一行状态为j的方案书.考虑下如果我们让矩阵S和S相乘会有什么意义,考虑一下会发现S*S的意义当某行状态为i,接着其后面第2行的状态为j的可行

HDU5863 cjj&#39;s string game(DP + 矩阵快速幂)

题目 Source http://acm.split.hdu.edu.cn/showproblem.php?pid=5863 Description cjj has k kinds of characters the number of which are infinite. He wants to build two strings with the characters. The lengths of the strings are both equal to n. cjj also def

HDU 5434 Peace small elephant 状压dp+矩阵快速幂

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: 108 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理)

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理) 题意:给出若干个模式串,总长度不超过40,对于某一个字符串,它有一个价值,对于这个价值的计算方法是这样的,设初始价值为V=1,假如这个串能匹配第k个模式串,则V=V*prime[k]*(i+len[k]),其中prime[k]表示第k个素数,i表示匹配的结束位置,len[k]表示第k个模式串的长度(注意,一个字符串可以多次匹配同意个模式串).问字符集为'A'-'Z'的字符,组成的所有的长为L的字符串,

zoj3690--Choosing number(dp,矩阵快速幂)

Choosing number Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Description There are n people standing in a row. And There are m numbers, 1.2...m. Every one should choose a number. But if two persons standing