Links
洛谷_P2579[ZJOI2005]沼泽鳄鱼
SSL_P2511沼泽鳄鱼
居然有点想接触一下鳄鱼这种生物…
题目
解
由于鳄鱼的活动周期只有2,3,4。
所以很容易得到一个为期12的大周期。
于是我们可以先得出大周期矩阵。先用单位矩阵乘上k/12个。
然后再一个个处理状态,分别乘上。
我们设矩阵 a[i][j] 为 从i点走到j点的方案数。
这样,两个矩阵相乘便可以得到下一个单位时间的矩阵。
我们便可以构建12个状态的矩阵,将鳄鱼会出现的位置填掉。
注意点和时间都是从0开始的,由于矩阵乘法定义方面我用了之前的代码,所以输入的时候便处理了一下。
Code
#include<cstdio>
int n, m, end, start, k, t, x, y, nfish, pst[10];
struct asdf{
int n, m;
int jz[71][71];
} E,a,A[15],K;
asdf operator *(asdf aa, asdf bb){
//定义矩阵乘法
asdf cc;
cc.n = aa.n;
cc.m = bb.m;
for(int i = 1; i <= cc.n; ++i)
for(int j = 1 ;j <= cc.m; ++j)
cc.jz[i][j] = 0;
for(int l = 1; l <= aa.m; ++l)
for(int i = 1; i <= cc.n; ++i)
for(int j = 1; j <= cc.m; ++j)
cc.jz[i][j] = (cc.jz[i][j] + aa.jz[i][l] * bb.jz[l][j] % 10000)% 10000;
return cc;
}
asdf ksm(int now){
//构建出来的矩阵的快速幂
asdf ll = E;
now--;
while(now>0)
{
if(now & 1) ll = ll * E;
E = E * E;
now >>= 1;
}
return ll;
}
int main(){
scanf("%d%d%d%d%d", &n, &m, &start, &end, &k);
++start; ++end; a.n = a.m = n; E.n = E.m = n;
for(int i = 1; i <= m; ++i){
scanf("%d%d", &x, &y);
++x; ++y; //因为点从0开始
a.jz[x][y] = a.jz[y][x] = 1; //这条路可以走
}
scanf("%d", &nfish);
for(int i = 1; i <= 12; ++i){
A[i] = a; //初始值
A[i].n = A[i].m = n;
}
for(int i = 1; i <= n; ++i){
//单位矩阵
for(int j = 1; j <= n; ++j)
E.jz[i][j] = 0;
E.jz[i][i] = 1;
}
for(int i = 1; i <= nfish; ++i){
scanf("%d",&t);
for(int i = 0; i < t; ++i){
scanf("%d", &pst[i]); //位置,position(雾
++pst[i];
}
for(int j = 1; j <= 12; ++j) //第j周期
for(int l = 1; l <= n; ++l) //所有点都不能到鳄鱼出现的点
A[j].jz[l][pst[j%t]] = 0;
}
if(k >= 12){
//计算答案
for(int i = 1; i <= 12; ++i) E = E * A[i]; //乘大周期
K = ksm(k/12);
}
else K = E;
for(int i = 1; i <= k % 12; ++i) //周期内。
K = K * A[i];
printf("%d",K.jz[start][end]); //输出
}