矩阵解决置换的问题
hdu2371
/*********************
http://acm.hdu.edu.cn/showproblem.php?pid=2371
题意:给定一个n,k,其中n表示字符串大小,同时也是置换的序列的大小
k表示置换的次数,再输入一个字符串,求一个初始串,使这个串通过k次
置换后变成我们输入的串
思路:以前是给定初始串求结果,这次是给定结果求初始串,只需要将置换
规则取反就可以了
即把置换op1变成op ,在这儿op1取2 3 1 5 4
op1 2 3 1 5 4 op 3 1 2 5 4
位置 1 2 3 4 5 ---> 1 2 3 4 5 -——>op[op1[i]]=i;
置换m次就快速求幂
*********************/
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#define N 85
#define mod 1000000007
#define lint long long
using namespace std;
struct matrix
{
int h,l;
int a[N][N];
void clear()
{
h=l=0;
memset(a,0,sizeof(a));
}
matrix operator +(const matrix &b)const
{
matrix c;
c.clear();
c.h=h;
c.l=l;
for(int i=1; i<=h; i++)
{
for(int j=1; j<=l; j++)
{
c.a[i][j]=a[i][j]+b.a[i][j];
}
}
return c;
}
matrix operator *(const matrix &b)const
{
matrix c;
c.clear();
c.h=h;
c.l=b.l;
for(int i=1; i<=h; i++)
{
for(int j=1; j<=b.l; j++)
{
for(int k=1; k<=l; k++)
{
c.a[i][j]+=a[i][k]*b.a[k][j];
}
}
}
return c;
}
};
matrix pow(matrix a,int k)
{
matrix ans;
ans.clear();
ans.h=ans.l=a.h;
for(int i=1; i<=a.h; i++)
{
ans.a[i][i]=1;
}
while(k)
{
if(k&1)
{
ans=ans*a;
}
k>>=1;
a=a*a;
}
return ans;
}
void print(matrix B)
{
int i,j;
for(i=1; i<=B.h; i++)
{
for(j=1; j<=B.l; j++)
printf("%d ",B.a[i][j]);
printf("\n");
}
printf("+++++++++\n");
}
int op1[N],op[N];
char str[N];
int n,k;
matrix a,b;
int main()
{
//freopen("C:\\Users\\Administrator\\Desktop\\in.txt" , "r" , stdin);
while(~scanf("%d%d",&n,&k))
{
if(n==0&&k==0)break;
for(int i=1;i<=n;i++)
{
scanf("%d",&op1[i]);
}
for(int i=1;i<=n;i++)
{
op[op1[i]]=i;
}
getchar();
//scanf("%s",str+1);
gets(str+1);
a.clear();
a.h=n,a.l=n;
for(int i=1;i<=n;i++)
{
a.a[i][op[i]]=1;
}
a=pow(a,k);
b.clear();
b.h=n,b.l=1;
for(int i=1;i<=n;i++)
{
b.a[i][1]=i;
}
a=a*b;
//print(a);
for(int i=1;i<=n;i++)
{
printf("%c",str[a.a[i][1]]);
}
printf("\n");
}
return 0;
}
voj1049
/**************************
https://vijos.org/p/1049
题意:顺次给出m 个置换,反复使用这m 个置换对初始序列进行操作,问k 次置换后
的序列。m<=10, k<2^
思路:首先将这m个置换“合并”起来(算出这m个置换的乘积),然后接下来我们需要执行这个置
换k/m 次(取整,若有余数则剩下几步模拟即可)。注意任意一个置换都可以表示成矩阵的形式。
例如,将1 2 3 4 置换为3 1 2 4 ,相当于下面的矩阵乘法:
| 0 0 1 0 | | 1 | | 3 |
| 1 0 0 0 | * | 2 | = | 1 |
| 0 1 0 0 | | 3 | | 2 |
| 0 0 0 1 | | 4 | | 4 |
置换k/m 次就相当于在前面乘以k/m 个这样的矩阵。我们可以二分计算出该矩阵的k/m 次
方,再乘以初始序列即可。
***************************/
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#define N 101
#define mod 1000000007
#define lint long long
using namespace std;
struct matrix
{
int h,l;
int a[N][N];
void clear()
{
h=l=0;
memset(a,0,sizeof(a));
}
matrix operator +(const matrix &b)const
{
matrix c;
c.clear();
c.h=h;
c.l=l;
for(int i=1; i<=h; i++)
{
for(int j=1; j<=l; j++)
{
c.a[i][j]=a[i][j]+b.a[i][j];
}
}
return c;
}
matrix operator *(const matrix &b)const
{
matrix c;
c.clear();
c.h=h;
c.l=b.l;
for(int i=1; i<=h; i++)
{
for(int j=1; j<=b.l; j++)
{
for(int k=1; k<=l; k++)
{
c.a[i][j]+=a[i][k]*b.a[k][j];
}
}
}
return c;
}
};
matrix pow(matrix a,int k)
{
matrix ans;
ans.clear();
ans.h=ans.l=a.h;
for(int i=1; i<=a.h; i++)
{
ans.a[i][i]=1;
}
while(k)
{
if(k&1)
{
ans=ans*a;
}
k>>=1;
a=a*a;
}
return ans;
}
void print(matrix B)
{
int i,j;
for(i=1; i<=B.h; i++)
{
for(j=1; j<=B.l; j++)
printf("%d ",B.a[i][j]);
printf("\n");
}
printf("+++++++++\n");
}
int n,m,k;
int op[N][N];
int main()
{
//freopen("C:\\Users\\Administrator\\Desktop\\in.txt" , "r" , stdin);
while(scanf("%d%d%d",&n,&m,&k)==3)
{
matrix a,e,b,c,d;
e.clear();//µ¥Î»¾ØÕó
e.h=n,e.l=n;
for(int i=1; i<=n; i++)
{
e.a[i][i]=1;
}
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&op[i][j]);
}
a.clear();
a.h=n,a.l=n;
for(int j=1; j<=n; j++)
{
a.a[j][op[i][j]]=1;
}
e=a*e;
//print(e);
}
b.clear();
b.h=n,b.l=n;
b=pow(e,k/m);
//print(b);
if(k%m)
{
for(int i=1; i<=k%m; i++)
{
c.clear();
c.h=n,c.l=n;
for(int j=1; j<=n; j++)
{
c.a[j][op[i][j]]=1;
}
b=c*b;
}
}
//print(b);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(b.a[i][j]==1)
{
printf("%d",j);
if(i!=n)
printf(" ");
else
printf("\n");
}
}
}
/*
d.clear();
d.h=n;
d.l=1;
for(int i=1;i<=n;i++)
{
d.a[i][1]=i;
}
b=b*d;
for(int i=1;i<n;i++)
{
printf("%d ",b.a[i][1]);
}
printf("%d\n",b.a[n][1]);
*/
}
return 0;
}