【BZOJ-4688】One-Dimensional 矩阵乘法

4688: One-Dimensional

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 19  Solved: 12
[Submit][Status][Discuss]

Description

考虑一个含有 N 个细胞的一维细胞自动机。细胞从 0 到 N-1 标号。每个细胞有一个被表示成一个小于 M 的非负整数的状态。细胞的状态会在每个整数时刻发生骤变。我们定义 S(i,t)  表示第 i 个细胞在时刻 t 的状态。在时刻 t+1 的状态被表示为 S(i,t+1)=(A×S(i-1,t)+B×S(i,t)+C×S(i+1,t) )  mod M ,其中 A,B,C 是给定的非负整数。对于 i<0 或 N≤i ,我们定义 S(i,t)=0 。给定一个自动机的定义和其细胞在时刻 0 的初始状态,你的任务是计算时刻 T 时每个细胞的状态。

Input

输入包含多组测试数据。每组数据的第一行包含六个整数 N,M,A,B,C,T ,满足 0<N≤50,0<M≤1000,0≤A,B,C<M,0≤T≤〖10〗^9  。第二行包含 N 个小于 M 的非负整数,依次表示每个细胞在时刻 0 的状态。输入以六个零作为结束。

Output

对于每组数据,输出N个小于M的非负整数,每两个相邻的数字之间用一个空格隔开,表示每个细胞在时刻T的状态。

Sample Input

5 4 1 3 2 0
0 1 2 0 1
5 7 1 3 2 1
0 1 2 0 1
5 13 1 3 2 11
0 1 2 0 1
5 5 2 0 1 100
0 1 2 0 1
6 6 0 2 3 1000
0 1 2 0 1 4
20 1000 0 2 3 1000000000
0 1 2 0 1 0 1 2 0 1 0 1 2 0 1 0 1 2 0 1
30 2 1 0 1 1000000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
30 2 1 1 1 1000000000
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
30 5 2 3 1 1000000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0

Sample Output

0 1 2 0 1
2 0 0 4 3
2 12 10 9 11
3 0 4 2 1
0 4 2 0 4 4
0 376 752 0 376 0 376 752 0 376 0 376 752 0 376 0 376 752 0 376
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 3 2 2 2 3 3 1 4 3 1 2 3 0 4 3 3 0 4 2 2 2 2 1 1 2 1 3 0

HINT

Source

鸣谢Tangjz提供试题

Solution

数据范围一眼矩乘

构造矩阵$y=\begin{bmatrix}B& C& 0& ....& 0& 0& 0& \\ A& B& C& ....& 0& 0& 0& \\ & & & ....& & & & \\ 0& 0& 0& ....& A& B& C& \\ 0& 0& 0& ....& 0& A& B& \end{bmatrix}$

然后答案就是的$x*y^{T}$

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0; char ch=getchar();
    while (ch<‘0‘ || ch>‘9‘) {ch=getchar();}
    while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
    return x;
}
int N,M,A,B,C,T;
struct MatrixNode{int a[51][51];}x,y;
inline MatrixNode mul(MatrixNode a,MatrixNode b)
{
    MatrixNode c;
    for (int i=1; i<=N; i++)
        for (int j=1; j<=N; j++)
            c.a[i][j]=0;
    for (int k=1; k<=N; k++)
        for (int i=1; i<=N; i++)
            if (a.a[i][k])
                for (int j=1; j<=N; j++)
                    if (b.a[k][j])
                        c.a[i][j]=(c.a[i][j]+(a.a[i][k]*b.a[k][j]))%M;
    return c;
}
inline MatrixNode quick_pow(MatrixNode a,int b)
{
    MatrixNode re;
    for (int i=1; i<=N; i++)
        for (int j=1; j<=N; j++)
            re.a[i][j]=i==j? 1:0;
    for (int i=b; i; i>>=1,a=mul(a,a))
        if (i&1) re=mul(re,a);
    return re;
}
void Debug(MatrixNode x)
{
    puts("start");
    for (int i=1; i<=N; i++,puts(""))
        for (int j=1; j<=N; j++)
            printf("%d ",x.a[i][j]);
    puts("end");
}
int main()
{
    while (scanf("%d%d%d%d%d%d",&N,&M,&A,&B,&C,&T))
        {
            if (!(N+M+A+B+C+T)) break;
            for (int i=1; i<=N; i++) x.a[1][i]=read();
            for (int i=1; i<=N; i++)
                for (int j=1; j<=N; j++)
                    y.a[i][j]=0;
            //Debug(x);
            for (int i=1; i<=N; i++)
                y.a[i][i+1]=A,y.a[i][i]=B,y.a[i][i-1]=C;
            //Debug(y);
            MatrixNode t=quick_pow(y,T);
            //Debug(t);
            x=mul(x,t);
            printf("%d",x.a[1][1]);
            for (int i=2; i<=N; i++) printf(" %d",x.a[1][i]);
            puts("");
        }
    return 0;
}
时间: 2024-12-20 01:13:55

【BZOJ-4688】One-Dimensional 矩阵乘法的相关文章

BZOJ 1297 SCOI2009 迷路 矩阵乘法

题目大意:给定一个邻接矩阵,求1~n的边权恰好为T的路径条数 考虑当所有边权都是1的时候 那么显然邻接矩阵自乘T次之后a[1][n]就是答案 因为当边权为1的时候a[i][j]可以表示从第i个点转移到第j个点的方案数 显然这个符合矩乘的定义 现在边权最大为9 那么将一个点拆成9个 第i个点拆成的第j+1个点向第j个点连一条边权为1的边 那么i->j有一条边权为k的边等价于i向j拆成的第k个点连边 #include <cstdio> #include <cstring> #in

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

矩阵乘法专题2——bzoj 1706 [usaco2007 Nov] relays 奶牛接力跑 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24960651 [原题] 1706: [usaco2007 Nov]relays 奶牛接力跑 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 340  Solved: 162 [Submit][Status] Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力

矩阵乘法专题3——bzoj 1898 [Zjoi2004]Swamp 沼泽鳄鱼 题解

[原题] 1898: [Zjoi2004]Swamp 沼泽鳄鱼 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 425  Solved: 256 [Submit][Status] Description 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎然,引来不少游客.为了让游玩更有情趣,人们在池塘的中央建设了几座石墩和石桥,每座石桥连接着两座石墩,且每两座石墩之间至多只有一座石桥.这

矩阵乘法专题4——bzoj 2326 [HNOI2011] 数学作业 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24963747 [原题] 2326: [HNOI2011]数学作业 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 853  Solved: 473 [Submit][Status] Description [分析]我们按数字的位数来划分.对于K位数,我们就可以专门设计一个矩阵来计算. 然后就是注意细节了. [代码] #include

[BZOJ 1875] [SDOI 2009] HH去散步【矩阵乘法】

题目链接:BZOJ - 1875 题目分析: 这道题如果去掉“不会立刻沿着刚刚走来的路走回”的限制,直接用邻接矩阵跑矩阵乘法就可以了.然而现在加了这个限制,建图的方式就要做一些改变.如果我们把每一条边看做点建矩阵,那么每次从一条边出发都只会到其他的边,不能仍然在这条边上“停留”,所以这就可以满足题目的限制.将每条边拆成两条单向边,比如一条编号为 4,一条编号为 5.那么 4^1=5, 5^1=4.这样只要不从第 i 条边走到 i 或 i^1 就可以了.初始的矩阵中以 A 为起点的边到达的方案数为

[BZOJ 2326] [HNOI2011] 数学作业 【矩阵乘法】

题目链接:BZOJ - 2326 题目分析 数据范围达到了 10^18 ,显然需要矩阵乘法了! 可以发现,向数字尾部添加一个数字 x 的过程就是 Num = Num * 10^k + x .其中 k 是 x 的位数. 那么位数相同的数字用矩阵乘法处理就可以了. [Num, x, 1] * [10^k, 0, 0] = [Num*10^k+x, x+1, 1] [      1, 0, 0] [      0, 1, 1] 枚举位数,做多次矩阵乘法. 其中两个整数相乘可能会爆 LL ,那么就用类似

【BZOJ 2738】 矩阵乘法

2738: 矩阵乘法 Time Limit: 20 Sec Memory Limit: 256 MB Submit: 841 Solved: 351 [Submit][Status][Discuss] Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. Input 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N*N个数,表示这个矩阵: 再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角.

[BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j 位的字符串个数,然后转移就是可以从第 j 位加上一个字符转移到另一个位置. 然而..我并没有写过KMP + DP,我觉得还是写AC自动机+DP比较简单..于是,尽管只有一个模式串,我还是写了AC自动机+DP. 然后就是建出AC自动机,f[i][j] 表示长度为 i ,走到节点 j 的字符串的个数.

【CDQ】BZOJ 2738 矩阵乘法

题意:给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数 思路: 整体二分+二维树状数组 二分询问的答案mid,将数值小等mid的全部插入二维树状数组 然后查询每个矩阵内的元素个数,若数量>K-1则放左边,否则放右边 继续向下分治,左边二分l-mid,右边mid-r 代码: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include