poj3735—Training little cats(特殊操作转化为矩阵操作)

题目链接:http://poj.org/problem?id=3735

题目意思:

调教猫咪:有n只饥渴的猫咪,现有一组羞耻连续操作,由k个操作组成,全部选自:

1. g i 给第i只猫咪一颗花生

2. e i 让第i只猫咪吃光它的花生

3. s i j 交换猫咪i与猫咪j的花生

现将上述一组连续操作做m次后,求每只猫咪有多少颗花生?

思路:这道题难点在如何把这种奇怪的操作转化为矩阵操作,网络上看到一个画的很好的图,这里直接偷过来。

现在,对于每一个操作我们都可以得到一个转置矩阵,把k个操作的矩阵相乘我们可以得到一个新的转置矩阵T。A * T 表示我们经过一组操作,类似我们可以得到经过m组操作的矩阵为 A * T ^ m,最终矩阵的[0][1~n]即为答案。

上述的做法比较直观,但是实现过于麻烦,因为要构造k个不同矩阵。有没有别的方法可以直接构造转置矩阵T?答案是肯定的。

我们还是以单位矩阵为基础:

对于第一种操作g i,我们使Mat[0][i] = Mat[0][i] + 1
对于第二种操作e i,我们使矩阵的第i列清零;
对于第三种操作s i j,我们使第i列与第j列互换。
这样实现的话,我们始终在处理一个矩阵,免去构造k个矩阵的麻烦。
至此,构造转置矩阵T就完成了,接下来只需用矩阵快速幂求出 A * T ^ m即可,还有一个注意的地方,该题需要用到long long。

这里还要说一下T*A=A*T的转置。

代码:

 1 //Author: xiaowuga
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define maxx INT_MAX
 6 #define minn INT_MIN
 7 #define inf 0x3f3f3f3f
 8 #define N  105
 9 using namespace std;
10 typedef long long ll;
11 ll  n,size;//第n项,矩阵大小
12 struct Matrix{
13     ll mat[N][N];
14     void clear(){
15         memset(mat,0,sizeof(mat));
16     }
17     Matrix operator * (const Matrix & m) const{
18         Matrix tmp;
19         int i ,j,k;
20         tmp.clear();
21         for( i=0;i<size;i++)
22             for( k=0;k<size;k++){
23                 if(mat[i][k]==0) continue;
24                 for( j=0;j<size;j++){
25                     tmp.mat[i][j]+=mat[i][k]*m.mat[k][j];
26                 }
27             }
28         return tmp;
29     }
30 };
31 void POW(Matrix m,ll k){
32     Matrix ans;
33     memset(ans.mat,0,sizeof(ans.mat));
34     for(int i=0;i<size;i++) ans.mat[i][i]=1;
35     while(k){
36         if(k&1) ans=ans*m;
37         k/=2;
38         m=m*m;
39     }
40     for(int i=1;i<size;i++){
41         cout<<ans.mat[0][i]<<" ";
42     }
43     cout<<endl;
44 }
45 int main() {
46     Matrix m;
47     int k;
48     while(cin>>size>>n>>k&&(size+n+k)){
49         size++;
50         m.clear();
51         for(int i=0;i<size;i++) m.mat[i][i]=1;
52         for(int i=0;i<k;i++){
53             char t[5];
54             int num1,num2;
55             cin>>t;
56             if(t[0]==‘g‘){
57                 cin>>num1;
58                 m.mat[0][num1]++;
59             }
60             else if(t[0]==‘e‘){
61                 cin>>num1;
62                 for(int j=0;j<size;j++){
63                     m.mat[j][num1]=0;
64                 }
65             }
66             else{
67                 cin>>num1>>num2;
68                 for(int j=0;j<size;j++)
69                     swap(m.mat[j][num1],m.mat[j][num2]);
70             }
71         }
72         POW(m,n);
73     }
74     return 0;
75 }

时间: 2024-12-25 13:06:41

poj3735—Training little cats(特殊操作转化为矩阵操作)的相关文章

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坐标转化中的平移矩阵和缩放矩阵?没错,就是这

卷积操作转化成矩阵乘法

参考:https://petewarden.com/2015/04/20/why-gemm-is-at-the-heart-of-deep-learning/ 平常都是无脑使用Pytorch提供的nn.Conv2d方法,但是并不关心具体该如何实现,原来是把卷积操作转化成矩阵乘法,而不是真的通过滑动卷积核来做卷积,下面做具体介绍. 首先看一下下面的示意图,左边是输入图像,右边是卷积核(为方便说明,只用了一个卷积核). 下面是用这个卷积核对输入图像做卷积操作,最后得到一个2维的平面 由下图可以看到卷

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

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

Training little cats(poj3735,矩阵快速幂)

Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10737   Accepted: 2563 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 t

poj 3735 Training little cats 矩阵

假设n=3 构造矩阵[1,0,0,0] 对于g 1操作,构造矩阵(0行i列++) 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 对于e 1操作,构造矩阵 (i整列清空) 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 对于s 1 2操作,构造矩阵 (i,j整列交换) 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 将k次操作依次按上述构造矩阵,得到一个轮回的转置矩阵.做m次快速幂就行了. 最坑的地方在于,答案要用longlong存,而longlo

矩阵快速幂 POJ 3735 Training little cats

题目传送门 1 /* 2 题意:k次操作,g:i猫+1, e:i猫eat,s:swap 3 矩阵快速幂:写个转置矩阵,将k次操作写在第0行,定义A = {1,0, 0, 0...}除了第一个外其他是猫的初始值 4 自己讲太麻烦了,网上有人讲的很清楚,膜拜之 5 详细解释:http://www.cppblog.com/y346491470/articles/157284.html 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #inc

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次后,问每只猫有多少颗花生? 再一次感受到了矩阵的强大...循环m次,且m这么大,很容易想到构造转换矩阵,但如何构造是个问题.尤其是第一种操作,第i只猫增加一个花生.具体构造方法是把矩阵扩大为(

POJ 3735 Training little cats 矩阵快速幂应用

点击打开链接 Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9807   Accepted: 2344 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

[POJ 3735] Training little cats (构造矩阵、矩阵快速幂)

Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9613   Accepted: 2296 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 th