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 to supervise the cats to do his exercises. Facer's great exercise for cats contains three different moves: Input The input file consists of multiple test cases, ending with three zeroes "0 0 0". For each test case, three integers n, m and k are given firstly, where n is the number of cats and k is the length of the move sequence. The following k lines describe the sequence. Output For each test case, output n numbers in a single line, representing the numbers of peanuts the cats have. Sample Input 3 1 6 g 1 g 2 g 2 s 1 2 g 3 e 2 0 0 0 Sample Output 2 0 1 Source |
解题报告: WA/TLE很久的一道题。
用long long TLE, unsigned WA,纠结至死……无奈看Discuss,发现了惊人的答案:矩阵乘法优化。其实以前就知道的。如果某一行很多个0,可以先判断是否为0,是就不用乘了。这样乘法的复杂度从100W直接降到1W左右(每行最多两个数不为0),乘上m的快速幂也不会超时了。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int SIZE=101;
typedef long long LL;
int n;
struct Matrix
{
LL a[SIZE][SIZE];
Matrix(int t=0)
{
memset(a, 0, sizeof(a));
for(int i=0;i<SIZE;i++) a[i][i]=t;
}
Matrix operator*(const Matrix& b) const
{
Matrix c;
for(int k=0;k<=n;k++)
for(int i=0;i<=n;i++) if(a[i][k])
for(int j=0;j<=n;j++) if(b.a[k][j])
c.a[i][j]+=a[i][k]*b.a[k][j];
return c;
}
};
Matrix powM(Matrix a, int b)
{
Matrix res(1);
while(b)
{
if(b&1)
res=res*a;
a=a*a;
b>>=1;
}
return res;
}
int main()
{
int m, k;
while(~scanf("%d%d%d", &n, &m, &k) && (n||m||k))
{
Matrix op(1);
while(k--)
{
char ch[2];
scanf("%s", ch);
if(ch[0]=='g')
{
int t;
scanf("%d", &t);
op.a[0][t]++;
}
else if(ch[0]=='e')
{
int t;
scanf("%d", &t);
for(int i=0;i<=n;i++)
op.a[i][t]=0;
}
else
{
int a, b;
scanf("%d%d", &a, &b);
for(int i=0;i<=n;i++)
swap(op.a[i][a], op.a[i][b]);
}
}
op=powM(op, m);
for(int i=1;i<=n;i++)
printf("%lld ", op.a[0][i]);
puts("");
}
}