告别

来源:互联网 发布:英国博士 知乎 编辑:程序博客网 时间:2024/04/28 19:30

题目大意

一个n的排列,每次可以选择三个不同位置(这三个位置有序,(2,1,3)与(1,2,3)不同),然后对它们进行一次轮换。
只能操作m次,某一次操作过后当前排列变成了目标排列则停止操作。
每次均等概率选择三个有序位置进行操作。
在模意义下求m次操作内变成目标排列的概率。

设状态

首先可以扭转初始排列和目标排列,使得目标排列变成有序的(就是变成1,2,3……n)
我们知道可以用置换来表示一个排列,目标排列此时对应n个单位置换,同时n个单位置换也一定只对应目标排列。
对于两种置换,如果其中所有置换长度组成的多重集合完全相同,能拓展出的状态也完全相同,因此应该考虑缩到一起。
这样子状态只有135种。
暴力枚举每种状态,然后可以构造出与其对应的一个可行排列,再暴力枚举三个有序位置,然后再找会变成哪个状态(可以二分或map)
由于走到目标状态就停止操作,因此目标状态不能有连向其他状态的边,只能有一个自环(方便我们得到m次以内而不是恰好m次)
得到转移矩阵后可以做矩阵乘法。

#include<cstdio>#include<algorithm>#include<map>#include<vector>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=150+10,mo=998244353;typedef long long ll;vector<int> now;map<vector<int>,int> ha;int c[maxn][20];int dis[maxn][maxn],ans[maxn][maxn],o[maxn][maxn],sta[60],a[20],b[20],d[20],ts[20],p[20];bool bz[20];int i,j,k,l,t,n,m,sid,tid,tot,top,sum,cnt,w1,w2,w3,num;int quicksortmi(int x,int y){    if (!y) return 1;    int t=quicksortmi(x,y/2);    t=(ll)t*t%mo;    if (y%2) t=(ll)t*x%mo;    return t;}void dfs(int x,int dow,int y){    if (!y){        int i;        top++;        fo(i,1,x-1) c[top][i]=p[i];        c[top][0]=x-1;        now.clear();        fo(i,1,x-1) now.push_back(p[i]);        ha[now]=top;        return;    }    int i;    fo(i,dow,y){        p[x]=i;        dfs(x+1,i,y-i);    }}int getid(){    int i;    now.clear();    fo(i,1,cnt) now.push_back(d[i]);    return ha[now];}int change(int x,int y,int z){    int i;    fo(i,1,n) b[i]=a[i];    int t=b[x];    b[x]=b[y];    b[y]=b[z];    b[z]=t;    cnt=0;    fo(i,1,n) bz[i]=0;    fo(i,1,n)        if (!bz[i]){            t=0;            j=i;            while (!bz[j]){                bz[j]=1;                t++;                j=b[j];            }            d[++cnt]=t;        }    sort(d+1,d+cnt+1);    return getid();}int main(){    freopen("goodbye.in","r",stdin);freopen("goodbye.out","w",stdout);    scanf("%d%d",&n,&m);    num=quicksortmi(n*(n-1)*(n-2),m);    num=quicksortmi(num,mo-2);    fo(i,1,n) scanf("%d",&a[i]);    fo(i,1,n) scanf("%d",&b[i]);    fo(i,1,n) ts[b[i]]=i;    fo(i,1,n) a[i]=ts[a[i]],b[i]=i;    dfs(1,1,n);    fo(i,1,n)        if (!bz[i]){            t=0;            j=i;            while (!bz[j]){                bz[j]=1;                t++;                j=a[j];            }            d[++cnt]=t;        }    sort(d+1,d+cnt+1);    sid=getid();    fo(i,1,n) d[i]=1;    cnt=n;    tid=getid();    fo(i,1,top){        j=1;k=1;        while (j<=c[i][0]){            fo(l,k,k+c[i][j]-2) a[l]=l+1;            a[k+c[i][j]-1]=k;            k+=c[i][j];            j++;        }        fo(w1,1,n)            fo(w2,1,n)                fo(w3,1,n)                      if (w1!=w2&&w1!=w3&&w2!=w3){                        j=change(w1,w2,w3);                        if (i==1) j=1;                        (dis[i][j]+=1)%=mo;                    }    }    //dis[tid][n+1]=dis[n+1][n+1]=1;    /*fo(i,1,n){        fo(j,1,n)            printf("%d ",dis[i][j]);        printf("\n");    }*/    //m++;    while (m){        sta[++sum]=m%2;        m/=2;    }    fo(i,1,top) ans[i][i]=1;    while (sum){        fo(i,1,top)            fo(j,1,top)                o[i][j]=0;        fo(k,1,top)            fo(i,1,top)                fo(j,1,top)                    o[i][j]=(o[i][j]+(ll)ans[i][k]*ans[k][j]%mo)%mo;        fo(i,1,top)            fo(j,1,top)                ans[i][j]=o[i][j];        if (sta[sum]){            fo(i,1,top)                fo(j,1,top)                    o[i][j]=0;            fo(k,1,top)                fo(i,1,top)                    fo(j,1,top)                        o[i][j]=(o[i][j]+(ll)ans[i][k]*dis[k][j]%mo)%mo;            fo(i,1,top)                fo(j,1,top)                    ans[i][j]=o[i][j];        }        sum--;    }    /*fo(i,1,n){        fo(j,1,n)            printf("%d ",ans[i][j]);        printf("\n");    }*/    fo(i,1,top)        fo(j,1,top)            dis[i][j]=0;    dis[1][sid]=1;    fo(i,1,top)        fo(j,1,top)            o[i][j]=0;    fo(k,1,top)        fo(i,1,top)            fo(j,1,top)                o[i][j]=(o[i][j]+(ll)dis[i][k]*ans[k][j]%mo)%mo;    fo(i,1,top)        fo(j,1,top)            ans[i][j]=o[i][j];    printf("%d\n",(ll)ans[1][1]*num%mo);}
0 0
原创粉丝点击