BZOJ 1898 ZJOI 2004 Swamp 沼泽鳄鱼 矩阵乘法

题目大意

给出一张无向图,这个图中有一些鱼,他们不同的时间会出现在固定的位置,呈周期性循环,一个人要在这个图上走,他不能和鱼同时在一个点上。问从s到t走k步有多少种方案。

思路

注意到鱼的循环只可能是2/3/4,也就是说最多经过12个时间点之后,状态又会和一开始相同。所以预处理12个矩阵用来转移。分为k/12和k%12来处理。 当鱼在一个位置上的时候,,当前时间从这个位置出发的一行和上一个时间到达这个点的一列需要清零。

CODE;int points;struct Matrix{int num[MAX][MAX];int w,h;Matrix(int _,int __):w(_),h(__) {memset(num,0,sizeof(num));}Matrix() {memset(num,0,sizeof(num));}Matrix operator *(const Matrix &a)const {Matrix re(w,a.h);for(int i = 1; i <= w; ++i)for(int j = 1; j <= a.h; ++j) {for(int k = 1; k <= h; ++k)re.num[i][j] += num[i][k] * a.num[k][j];re.num[i][j] %= MO;}return re;}void ClearHor(int line) {for(int i = 1; i <= points; ++i)num[line][i] = 0;}void ClearVer(int line) {for(int i = 1; i <= points; ++i)num[i][line] = 0;}}src[20];struct Fish{int cnt,num[10];void Read() {scanf(“%d”,&cnt);for(int i = 0; i < cnt; ++i)scanf(“%d”,&num[i]),++num[i];}}fish[MAX];int edges,s,t;long long k;int fishes;Matrix QuickPower(Matrix a,long long y){Matrix re(points,points);for(int i = 1; i <= points; ++i)re.num[i][i] = 1;while(y) {if(y&1) re = re * a;a = a * a;y >>= 1;}return re;}int main(){cin >> points >> edges >> s >> t >> k;++s,++t;Matrix map(points,points);for(int x,y,i = 1; i <= edges; ++i) {scanf(“%d%d”,&x,&y);++x,++y;map.num[x][y] = map.num[y][x] = 1;}for(int i = 0; i < 12; ++i)src[i] = map;cin >> fishes;for(int i = 1; i <= fishes; ++i)fish[i].Read();for(int i = 0; i < 12; ++i) {for(int j = 1; j <= fishes; ++j) {int pos = fish[j].num[i % fish[j].cnt];if(i)src[i – 1].ClearVer(pos);src[i].ClearHor(pos);}}Matrix base(points,points);for(int i = 1; i <= points; ++i)base.num[i][i] = 1;for(int i = 0; i < 12; ++i)base = base * src[i];Matrix ans = QuickPower(base,k / 12);k %= 12;for(int i = 0; i < k; ++i)ans = ans * src[i];cout << ans.num[s][t] << endl;return 0;}

坚韧是成功的一大要素,只要在门上敲得够久够大声,终会把人唤醒的。

BZOJ 1898 ZJOI 2004 Swamp 沼泽鳄鱼 矩阵乘法

相关文章:

你感兴趣的文章:

标签云: