日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

矩阵乘法(五):置换

發布時間:2023/12/15 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 矩阵乘法(五):置换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

矩陣乘法在一些置換問題上有著很好的應用,特別置換次數較多時,采用矩陣快速冪運算可以加快運算過程。

任意一個置換都能夠表示成矩陣的形式。比如,將序列1 2 3 4 置換為 3 1 2 4,相當于以下的矩陣乘法:

一般來說,對于序列1, 2, ..., n,若給出置換方法a1,a2,...,an,該置換方法表示將原序列的第pi位置上的元素換到第i位置上。

則可以構造置換矩陣P為: P[ai][i]=1 (1<=i<=n), 其余元素全為0。

顯然,置換矩陣每行只有一個元素為1,其余為0。

另外,構造的置換矩陣都是可逆的,并且它的逆矩陣等于它的轉置矩陣。

【例1】解碼字符串。

給定n個數,代表一個置換。一個長度為n的字符串s經過m次置換后變成另一個字符串t。

例如,輸入5個數:2 3 1 5 4 代表一個置換操作。字符串s為“hello”,經過3次置換操作

"hello" -> "elhol" -> "lhelo" -> "helol"后,可得到字符串t為“helol”。

輸入n、m和結果字符串t,輸出轉換前的原字符串s。

(1)編程思路。

由置換規則 2 3 1 5 4,可以快速構造用于字符串s轉換到t的置換矩陣P。

而從字符串t轉換到s顯然是逆操作,而置換矩陣的逆矩陣就是其轉置矩陣。因此,用于本題的置換矩陣PT應為:

構造好置換矩陣后,m次操作就是置換矩陣的m次冪,之后再乘以初始序列{1 2 3 4 ....n},然后輸出相應位置的字符就可以了。

(2)源程序。

#include <stdio.h>
#include <string.h>
struct Matrix
{
int mat[81][81]; // 存儲矩陣中各元素
};
Matrix matMul(Matrix a ,Matrix b,int n)
{
Matrix c;
memset(c.mat,0,sizeof(c.mat));
int i,j,k;
for (k = 1; k<=n ; k++)
for (i=1 ;i<=n ; i++)
if (a.mat[i][k]!=0)
for (j = 1 ;j<=n ;j++)
c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) ;
return c;
}
Matrix quickMatPow(Matrix a ,int n,int b) // n階矩陣a快速b次冪
{
Matrix c;
memset(c.mat ,0 ,sizeof(c.mat));
int i;
for (i = 1 ;i <= n ;i++)
c.mat[i][i] = 1;
while (b!=0)
{
if (b & 1)
c = matMul(c ,a ,n); // c=c*a;
a = matMul(a ,a ,n); // a=a*a
b /= 2;
}
return c;
}
int main()
{
int n,m,p[81],i;
Matrix a,b,ans;
char str[82];
while (scanf("%d%d",&n,&m) && n!=0 && m!=0)
{
memset(b.mat,0,sizeof(b.mat));
for (i=1;i<=n;i++)
b.mat[1][i]=i;
memset(a.mat,0,sizeof(a.mat));
for (i=1;i<=n;i++)
{
scanf("%d",&p[i]);
a.mat[i][p[i]]=1;
}
getchar();
gets(str);
ans=quickMatPow(a,n,m);
ans=matMul(b,ans,n);
for (i=1;i<=n;i++)
printf("%c",str[ans.mat[1][i]-1]);
printf("
");
}
return 0;
}

將此源程序提交給HDU 2371 “Decode the Strings”,可以Accepted。

【例2】送給圣誕夜的禮品。

已知序列1,2,3,…,n,給出m個置換操作, 例如某個置換操作6 1 3 7 5 2 4,表示把6位置上的元素換到1位置上,1位置上的元素換到2位置上…。

求原序列為1,2,3,……,n的序列按給出的m個置換操作的順序進行k次置換后得到的新序列。若k>m,則第m+1次置換操作做第1個置換操作,第m+2次置換操作做第2個置換操作,…。

數據說明: 1<=n<=100;1<=m<=10;1<=k<=2^31-1。

本題完整的描述可以參看https://vijos.org/p/1049。

(1)編程思路。

搞懂了例1,本題就容易入手了。m 個置換操作需要構造m個置換矩陣。

構造好置換矩陣后,先將m個置換矩陣乘起來,得到ans矩陣,則此時的ans矩陣相當進行了m次操作;再將ans矩陣進行k/m次冪,此時相當進行了k次操作。當然,由于k不一定整除m,因此還需按m個置換操作的順序進行k%m次的置換操作。

(2)源程序。

#include <stdio.h>
#include <string.h>
struct Matrix
{
int mat[101][101]; // 存儲矩陣中各元素
};
Matrix p[11];
Matrix matMul(Matrix a ,Matrix b,int n)
{
Matrix c;
memset(c.mat,0,sizeof(c.mat));
int i,j,k;
for (k = 1; k<=n ; k++)
for (i=1 ;i<=n ; i++)
if (a.mat[i][k]!=0)
for (j = 1 ;j<=n ;j++)
c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) ;
return c;
}
Matrix quickMatPow(Matrix a ,int n,int b) // n階矩陣a快速b次冪
{
Matrix c;
memset(c.mat ,0 ,sizeof(c.mat));
int i;
for (i = 1 ;i <= n ;i++)
c.mat[i][i] = 1;
while (b!=0)
{
if (b & 1)
c = matMul(c ,a ,n); // c=c*a;
a = matMul(a ,a ,n); // a=a*a
b /= 2;
}
return c;
}
int main()
{
int n,m,k,i,j,num,a[101];
Matrix ans;
scanf("%d%d%d",&n,&m,&k);
for (i=0;i<m;i++)
{
memset(p[i].mat,0,sizeof(p[i].mat));
for (j=1;j<=n;j++)
{
scanf("%d",&num);
p[i].mat[j][num]=1; // 構造的置換矩陣
}
}
memset(ans.mat,0,sizeof(ans.mat));
for (i=1;i<=n;i++)
ans.mat[i][i]=1;
for (i=0;i<m;i++)
ans=matMul(p[i],ans,n); // m個置換矩陣先乘起來,注意是左乘
ans=quickMatPow(ans,n,k/m);
for (i=0;i<k%m;i++)
ans=matMul(p[i],ans,n); // 剩余的k%m個矩陣相乘,代表剩余的k%m次操作
memset(a,0,sizeof(a));
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
a[i]=a[i]+(ans.mat[i][j])*j;
for (i=1;i<=n;i++)
printf("%d ",a[i]);
printf("
");
return 0;
}

總結

以上是生活随笔為你收集整理的矩阵乘法(五):置换的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。