正解:矩陣快速冪/tarjan+倍增
解題報告:
跟着神仙做神仙題系列III
這題首先一看到就會想到快速冪趴?就會jio得,哦也不是很難哦
然而,看下數據范圍,,,1×105,,,顯然開不下TT
所以考慮優化快速冪(或找環+倍增
兩種方法都港下趴
先說圖論好辣QwQ
大概是這樣的:
首先我們把每個座位都抽象成一個點,由它給我的A[]可以知道坐在每個座位上的人會移到哪兒
我們就可以理解為連了一條邊
顯然的是我們可以換了很多次之后換回來,於是就成了一個環了
然后我們就求一波強連通分量,這樣我們讀入k之后就能先給他取個膜讓k控制在一定范圍內嘛
然后之后再用下倍增的思想,這個我jio得還是挺好懂的?就是f[i][j]表示i這個點移動2<<j之后會去哪兒
然后就好辣!
get?
快速冪其實也不難,嘗試理解一下就能get
這個實在沒什么好說的大概扯下趴,,,
這樣的,顯然它是滿足結合律的,舉個eg,假如我要挪21次
那我可以一次一次挪,但這顯然比較慢,但我也可以這樣子:21=24+22+21
所以就用和快速冪一樣的思想,這么想吼,一樣是有個tmp有個ans
首先20系數是0,所以ans不變,tmp變成A[tmp]
然后21系數是1,所以ans變成A[tmp],tmp變成A[tmp]
然后22系數是1,所以ans變成A[tmp],tmp變成A[tmp]
然后23系數是0,所以ans不變,tmp變成A[tmp]
然后24系數是1,所以ans變成A[tmp],tmp變成A[tmp]
這個我jio得還是可以理解的趴?挺顯然的?
實在無法理解可以結合一下前面的倍增,其實這個和倍增是一樣的不過倍增是預處理就成立逆推而這個是順推而已(所以倍增會快一些,不過這個簡單打一些啊QwQ
(話說這題我jio得就是單純的快速冪啊,,,哪里是矩陣快速冪了,,,為什么我看到的兩篇都是說是矩陣快速冪啊,,,沒有get?
順便一提,這題的法二有個很新穎的名詞"群",似乎用那個更好解釋
然而我還沒學:D基礎都沒落實完的菜菜靈巧不配學新芝士嗚嗚嗚
所以詳見hl的博客
over!
然后兩個方法的代碼應該都會打的到時候都放上來QwQ

#include<bits/stdc++.h> using namespace std; #define ll long long #define rg register #define rp(i,x,y) for(register ll i=x;i<=y;++i) const ll N=100000; ll n,k,a[N],nw[N],tmp[N]; ll read() { rg char ch=getchar();rg ll x=0;rg bool y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar(); if(ch=='-')ch=getchar(),y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar(); return y?x:-x; } int main() { n=read();k=read();rp(i,1,n)a[i]=read(),nw[i]=i,tmp[i]=i; while(k) { if(k&1){rp(i,1,n)tmp[i]=nw[a[i]];rp(i,1,n)nw[i]=tmp[i];} rp(i,1,n)tmp[i]=a[a[i]];rp(i,1,n)a[i]=tmp[i];k>>=1; } rp(i,1,n)tmp[nw[i]]=i; rp(i,1,n)printf("%lld ",tmp[i]); return 0; }