GDOI2017模擬12 3 告別

2021-07-25 04:31:33 字數 1542 閱讀 3960

給出兩個1~n的排列a和b,可以進行m次操作,每次操作隨機選擇乙個三元組(i,j,k),將這個三元組所對應的數在a中進行輪換(即i->j,j->k,k->i)

求在m次操作之內將a變成b的概率,答案對998244353取模

n<=14,m<=1e9

乍一看根本無法下手啊。。。

看到n辣麼小m辣麼大就知道是矩乘可是不會做。。。

如果n再小一點我們可以直接維護狀態然後轉移,但這樣狀態太多了

我們考慮怎樣壓縮狀態數。。。

先把b對應成1~n的有序排列,然後我們就只需要對a進行輪換了。。。

乙個很好的思路是我們可以用a中的所有置換群來表示a。。。

我們這樣只用記錄每個置換群的大小就好了,因為只需要本質不同的。。。

b唯一對應n個1,所以不用擔心算重。。。

這樣設的狀態數是n的劃分數,n=14時為135

轉移的話先列舉狀態,隨便構造乙個滿足狀態的排列,然後暴力列舉三元組轉移,判斷轉移後的狀態是哪乙個,這個地方用hash/map/二分之類的就好了

然後把矩陣構造出來直接矩陣乘法就好了

#include 

#include

#include

#define fo(i,a,b) for(int i=a;i<=b;i++)

using

namespace

std;

typedef

long

long ll;

const

int n=15,m=135,mo=998244353;

int a[n],c[n],w[n],h[n],x,s,n,m,tot;

bool bz[n];

struct note

friend

bool

operator

< (note x,note y)

}q[m],d;

struct matrix

}g,t;

void dfs(int x,int la)

fo(i,la,n-x) d.a[i]++,dfs(x+i,i),d.a[i]--;

}int mi(int x,int y)

note displace(int *a)

return a;

}int find(note x)

return l;

}int main()

note a=displace(a);g.a[0][0]=n*(n-1)*(n-2);

fo(i,0,tot) if (q[i]==a)

fo(i,1,tot)

fo(j,1,n) fo(k,1,n) if (j!=k)

fo(l,1,n) if (j!=l&&k!=l)

}memcpy(t.a,g.a,sizeof(t.a));

for(m--;m;m/=2,g=g*g) if (m&1) t=t*g;

printf("%lld\n",(ll)t.a[s][0]*ni%mo);

}

GDOI2017模擬8 12 躲藏

給出乙個n m的網格圖,圖中有一些障礙節點。現在有a個男生和b個女生,還有乙個小標。男生要和女生配對,小標可以和任何乙個人配對。每一對cp 霧 只能待在乙個點。乙個點只能有一對cp。現在給出a b 1個人的初始座標,和他們的移動速度 即移動到4相鄰格仔所需的時間 所有人同時移動,求完成配對的最小時間...

GDOI2017模擬8 12 新車

平面上有乙個數軸,e點為目標點。你現在要開 車從w前往e,每移動1格需要1l油。你的油箱容量為s,初始時裝滿了98 汽油。數軸上有n個加油站,每個加油站提供98 95 92 中的一種。到了加油站你可以選擇加任意數量的油,你的油箱是茲瓷所有油甚至混合油的。你認為98 最吼,95 其次,92 跑的最慢。...

GDOI2017模擬11 5 總結

看到第一題,哇,數論題,不會啊,感覺要跪 正當我迷茫的時候,突然機房斷電了。啪的一聲大家的電腦都黑了!不知所措!沒辦法,只好等等。過了10分鐘左右,來電了,重新看了看第一題,也許是冷靜下來了,發現直接暴力分解質因數就能過!繼續看第二題,在草稿紙上推了一下,要用揹包,一開始以為會超時,但仔細想了想發現...