zoukankan      html  css  js  c++  java
  • 矩阵十题(4)

    经典题目4 VOJ1049

    题目链接:https://vijos.org/p/1049

    题目大意:顺次给出m个置换,反复使用这m个置换对初始序列进行操作,问k次置换后的序列。m<=10, k<2^31。
    首先将这m个置换“合并”起来(算出这m个置换的乘积),然后接下来我们需要执行这个置换k/m次(取整,若有余数则剩下几步模拟即可)。注意任意一个置换都可以表示成矩阵的形式。例如,将1 2 3 4置换为3 1 2 4,相当于下面的矩阵乘法:

    置换k/m次就相当于在前面乘以k/m个这样的矩阵。我们可以二分计算出该矩阵的k/m次方,再乘以初始序列即可。做出来了别忙着高兴,得意之时就是你灭亡之日,别忘了最后可能还有几个置换需要模拟。

    注意:这m个置换对应的矩阵相乘的时候必须左乘

    代码如下:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define N 110
     4 struct Matrix
     5 {
     6     int a[N][N];
     7 }origin,res,tmp,A,B,ans;
     8 int n;
     9 int op[N][N];
    10 Matrix mul(Matrix x,Matrix y)
    11 {
    12     int i,j,k;
    13     memset(tmp.a,0,sizeof(tmp.a));
    14     for(i=1;i<=n;i++)
    15         for(j=1;j<=n;j++)
    16             for(k=1;k<=n;k++)
    17                 tmp.a[i][j]+=x.a[i][k]*y.a[k][j];
    18     return tmp;
    19 }
    20 Matrix quickpow(Matrix B,int k)
    21 {
    22     int i;
    23     memset(res.a,0,sizeof(res.a));
    24     for(i=1;i<=n;i++)
    25         res.a[i][i]=1;
    26     while(k)
    27     {
    28         if(k&1)
    29             res=mul(res,B);
    30         B=mul(B,B);
    31         k>>=1;
    32     }
    33     return res;
    34 }
    35 void print(Matrix B)
    36 {
    37     int i,j;
    38     for(i=1;i<=n;i++)
    39     {
    40         for(j=1;j<=n;j++)
    41             printf("%d ",B.a[i][j]);
    42         printf("\n");
    43     }
    44     printf("+++++++++\n");
    45 }
    46 int main()
    47 {
    48     int m,i,k,j;
    49     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    50     {
    51         memset(B.a,0,sizeof(B.a));
    52         for(i=1;i<=n;i++)
    53             B.a[i][i]=1;
    54         for(i=1;i<=m;i++)
    55         {
    56             for(j=1;j<=n;j++)
    57                 scanf("%d",&op[i][j]);
    58             memset(A.a,0,sizeof(A.a));   //置换所对应的矩阵
    59             for(j=1;j<=n;j++)
    60                 A.a[j][op[i][j]]=1;
    61             B=mul(A,B);       //左乘
    62         //    print(B);
    63         }
    64         res=quickpow(B,k/m);   //执行k/m次
    65         memset(origin.a,0,sizeof(origin.a));
    66         for(i=1;i<=n;i++)   
    67             origin.a[i][1]=i;
    68         ans=mul(res,origin);   //乘以初始矩阵
    69         if(k%m)        //将剩余的几步模拟
    70         {
    71             for(i=1;i<=k%m;i++)
    72             {
    73                 memset(A.a,0,sizeof(A.a));
    74                 for(j=1;j<=n;j++)
    75                     A.a[j][op[i][j]]=1;
    76                 ans=mul(A,ans);
    77             }
    78         }
    79         for(i=1;i<=n;i++)
    80         {
    81             printf("%d",ans.a[i][1]);
    82             if(i<n)
    83                 printf(" ");
    84         }
    85         printf("\n");
    86     }
    87     return 0;
    88 }
    View Code

    hdu  2371  Decode the Strings

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2371

    题目大意:给出n 和m,给出n个数,代表一个置换,接着一个字符串s,s经过m次置换后变成另一个字符串,

    现在给出经过m次置换后的字符串,输出原始字符串s

    比如:5 3

            2 3 1 5 4

            hello

    需经过3次置换,则"hello" -> "elhol" -> "lhelo" -> "helol"

    思路:将置换规则取反(将p[i]位置上的数num[i]变成p[num[i]]上的数,例如,num:  2 3 1 5 4  变成  num:  3 1 2 5 4

                                                                                                             p: 1 2 3 4 5               p:  1 2 3 4 5  )

    然后将m次置换合并起来,即算出这m个置换的乘积(即origin^m),然后乘以初始序列[1 2 3 4 ....n],然后输出对应位置的字符即可。

    注意任意一个置换都可以表示成矩阵的形式。例如,将1 2 3 4置换为3 1 2 4,相当于下面的矩阵乘法:

    m次置换就相当于前面乘以m个这样的矩阵,用矩阵快速幂即可。

    代码如下:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define N 100
     4 struct Matrix
     5 {
     6     int a[N][N];
     7 }res,tmp,origin,A,ans;
     8 int n;
     9 int p[N],num[N];
    10 char s[N];
    11 Matrix mul(Matrix x,Matrix y)
    12 {
    13     int i,j,k;
    14     memset(tmp.a,0,sizeof(tmp.a));
    15     for(i=1;i<=n;i++)
    16         for(j=1;j<=n;j++)
    17             for(k=1;k<=n;k++)
    18                 tmp.a[i][j]+=x.a[i][k]*y.a[k][j];
    19     return tmp;
    20 }
    21 void quickpow(int k)  //矩阵快速幂
    22 {
    23     int i;
    24     memset(res.a,0,sizeof(res.a));
    25     for(i=1;i<=n;i++)
    26         res.a[i][i]=1;
    27     while(k)
    28     {
    29         if(k&1)
    30             res=mul(res,origin);
    31         origin=mul(origin,origin);
    32         k>>=1;
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     int m,i;
    39     while(scanf("%d%d",&n,&m)!=EOF)
    40     {
    41         if(n==0&&m==0)
    42             break;
    43         for(i=1;i<=n;i++)
    44             scanf("%d",&num[i]);
    45         for(i=1;i<=n;i++)   //将置换取反
    46             p[num[i]]=i;
    47         memset(origin.a,0,sizeof(origin.a));  //将置换用矩阵表示
    48         for(i=1;i<=n;i++)
    49             origin.a[i][p[i]]=1;
    50         getchar();
    51         gets(s);
    52         quickpow(m);   //乘以m次这样的矩阵
    53         memset(A.a,0,sizeof(A.a));  //原始序列[1 2 3 4 5 ...n]
    54         for(i=1;i<=n;i++)
    55             A.a[i][1]=i;
    56         ans=mul(res,A);   //与原始序列相乘
    57         for(i=1;i<=n;i++)
    58             printf("%c",s[ans.a[i][1]-1]);
    59           //  printf("%d ",ans.a[i][1]);
    60         printf("\n");
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    Oracle 按一行里某个字段里的值分割成多行进行展示
    Property or method "openPageOffice" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by
    SpringBoot 项目启动 Failed to convert value of type 'java.lang.String' to required type 'cn.com.goldenwater.dcproj.dao.TacPageOfficePblmListDao';
    Maven 设置阿里镜像
    JS 日期格式化,留作参考
    JS 过滤数组里对象的某个属性
    原生JS实现简单富文本编辑器2
    Chrome控制台使用详解
    android权限(permission)大全
    不借助第三方网站四步实现手机网站转安卓APP
  • 原文地址:https://www.cnblogs.com/frog112111/p/3089358.html
Copyright © 2011-2022 走看看