矩阵经典题目四:送给圣诞夜的礼品(使用m个置换实现对序列的转变)

https://vijos.org/p/1049

给出一个序列,含n个数。然后是m个置换,求对初始序列依次进行k次置换,求最后的序列。

先看一个置换,把置换表示成矩阵的形式,然后将m个置换乘起来。那么初始序列首先执行这个置换k/m次,然后顺次执行前k%m个置换,最后乘上初始矩阵。

最后注意矩阵乘法的顺序,A*B != B*A。

#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define C 240
#define S 20
using namespace std;

const int maxn = 110;

struct matrix
{
    int mat[maxn][maxn];
    int n,m;
    void init()
    {
        memset(mat,0,sizeof(mat));
        for(int i = 1; i <= 105; i++)
        {
            mat[i][i] = 1;
        }
    }
}M[11]; //将每一个置换表示出来。

int n,m;

matrix mul(matrix a, matrix b)
{
    matrix ans;
    memset(ans.mat,0,sizeof(ans.mat));
    ans.n = a.n;
    ans.m = b.m;
    for(int i = 1; i <= a.n ; i++)
    {
        for(int k = 1; k <= a.m; k++)
        {
            if(a.mat[i][k] == 0) continue;
            for(int j = 1; j <= b.m; j++)
                ans.mat[i][j] += a.mat[i][k]*b.mat[k][j];
        }
    }
    return ans;
}

matrix pow(matrix a, int n)
{
    matrix ans;
    ans.n = a.n;
    ans.m = a.m;
    ans.init();

    while(n)
    {
        if(n&1)
            ans = mul(ans,a);
        a = mul(a,a);
        n >>= 1;
    }
    return ans;
}

int main()
{
    int num,k,z;
    while(~scanf("%d %d %d",&n,&m,&k))
    {
        matrix a,b;
        a.init();
        a.m = a.n = n;
        b.n = n;
        b.m = 1;
        for(int i = 1; i <= n; i++)
            b.mat[i][1] = i;

        for(int i = 1; i <= m; i++)
        {
            memset(M[i].mat,0,sizeof(M[i].mat));
            M[i].m = M[i].n = n;
            for(int j = 1; j <= n; j++)
            {
                scanf("%d",&num);
                M[i].mat[j][num] = 1;
            }
            a = mul(M[i],a); //注意相乘的顺序
        }

        z = k/m;
        k = k%m;

        a = pow(a,z);
        for(int i = 1; i <= k; i++)
            a = mul(M[i],a);//注意相乘的顺序
        a = mul(a,b);
        for(int i = 1; i <= n; i++)
        {
            printf("%d",a.mat[i][1]);
            if(i == n)
                printf("\n");
            else printf(" ");
        }
    }
    return 0;
}

矩阵经典题目四:送给圣诞夜的礼品(使用m个置换实现对序列的转变)

时间: 2024-11-12 02:01:32

矩阵经典题目四:送给圣诞夜的礼品(使用m个置换实现对序列的转变)的相关文章

P1049送给圣诞夜的礼品(矩阵十大问题之四)

https://vijos.org/p/1049 P1049送给圣诞夜的礼品 Accepted 标签:组合数学送给圣诞夜的礼物[显示标签] 返回代码界面 | 关闭 Pascal Pascal C C++ Python 2.x Java 取消 | 清空代码 描述 当小精灵们把贺卡都书写好了之后.礼品准备部的小精灵们已经把所有的礼品都制作好了.可是由于精神消耗的缘故,他们所做的礼品的质量越来越小,也就是说越来越不让圣诞老人很满意.可是这又是没有办法的事情. 于是圣诞老人把礼品准备部的小精灵们聚集起来

送给圣诞夜的礼品

描述 当小精灵们把贺卡都书写好了之后.礼品准备部的小精灵们已经把所有的礼品都制作好了.可是由于精神消耗的缘故,他们所做的礼品的质量越来越小,也就是说越来越不让圣诞老人很满意.可是这又是没有办法的事情. 于是圣诞老人把礼品准备部的小精灵们聚集起来,说明了自己的看法:"现在你们有n个礼品,其质量也就是降序排列的.那么为了使得这个礼品序列保持平均,不像现在这样很有规律的降序,我这里有一个列表." "列表共有m行,这m行都称作操作(不是序列),每一行有n个数字,这些数字互不相同而且每

vijosP1049 送给圣诞夜的礼品

链接:https://vijos.org/p/1049 [思路] 快速幂+矩阵转换. 将m次矩阵的转换看作是一次快速幂中的乘法操作,这样可以用O(log(k/m))的时间求出矩阵进行k/m次操作后的结果,然后把剩下的k%m次矩阵转换补上即可. [代码] 1 #include<iostream> 2 #include<cstring> 3 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 4 using namespace std; 5

[vijos]1051送给圣诞夜的极光&lt;BFS&gt;

送给圣诞夜的极光 题目链接:https://www.vijos.org/p/1051 这是一道很水很水的宽搜水题,我主要是觉得自己在搜素这一块有点生疏于是随便找了一题练手,找到这么一道水题,原本以为可以一次过的,但是状况百出,我并不是很擅长bfs,我以前一直用的Pascal写bfs,但是Pascal没有队列,所以没有c++方便,所以这题我就直接用队列做了,然后完美的炸空间炸时间,后来改成递归调用才通过 思路:这一道题和一道宽搜入门题很像,基本上是一样的,这道题叫细胞个数 链接:http://co

矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)

https://www.vijos.org/p/1067 很容易推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵,其中右上角的(k-1)*(k-1)的矩阵是单位矩阵,第k行的每个数分别对应f[n-1],f[n-2],,f[n-k]的系数.然后构造一个k*1的矩阵,它的第i行代表f[i],是经过直接递推得到的.设ans[][]是第一个矩阵的n-k次幂乘上第二个矩阵,f[n]就是ans[k][1]. 注意:用__int64 #in

矩阵经典题目八:hdu 2175 How many ways??

http://acm.hdu.edu.cn/showproblem.php?pid=2157 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值 把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j.令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点).类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数.同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可.

洛谷 P1454 圣诞夜的极光 == codevs 1293 送给圣诞夜的极光

题目背景 圣诞夜系列~~ 题目描述 圣诞老人回到了北极圣诞区,已经快到12点了.也就是说极光表演要开始了.这里的极光不是极地特有的自然极光景象.而是圣诞老人主持的人造极光. 轰隆隆……烟花响起(来自中国的浏阳花炮之乡).接下来就是极光表演了. 人造极光其实就是空中的一幅幅n*m的点阵图像.只是因为特别明亮而吸引了很多很多小精灵的目光,也成为了圣诞夜最美丽的一刻. 然而在每幅n*m的点阵图像中,每一个点只有发光和不发光两种状态.对于所有的发光的点,在空中就形成了美丽的图画.而这个图画是以若干个(s

【VIJOS】p1051 送给圣诞夜的极光

描述 圣诞老人回到了北极圣诞区,已经快到12点了.也就是说极光表演要开始了.这里的极光不是极地特有的自然极光景象.而是圣诞老人主持的人造极光. 轰隆隆……烟花响起(来自中国的浏阳花炮之乡).接下来就是极光表演了. 人造极光其实就是空中的一幅幅n*m的点阵图像.只是因为特别明亮而吸引了很多很多小精灵的目光,也成为了圣诞夜最美丽的一刻. 然而在每幅n*m的点阵图像中,每一个点只有发光和不发光两种状态.对于所有的发光的点,在空中就形成了美丽的图画.而这个图画是以若干个(s个)图案组成的.对于图案,圣诞

矩阵经典题目六:poj 3070 Fibonacci

http://poj.org/problem?id=3070 按已构造好的矩阵,那么该矩阵的n次方的右上角的数便是f[n]. #include <stdio.h> #include <iostream> #include <map> #include <set> #include <list> #include <stack> #include <vector> #include <math.h> #inclu