康拓展開 P5367 模板 康托展開

2022-05-27 19:06:12 字數 1055 閱讀 5074

舉個栗子大家應該就能懂了:

我現在生成了1~5的全排列,求數列5  2  3  1  4是第幾個

5:有四個數比他小,他後面還有4個數,所以他的貢獻應該是4*4!

2:有乙個數比他小,他後面還有3個數,所以他的貢獻應該是1*3!

3:有兩個數比他小,他後面還有兩個數,但是其中2在前面出現過了,所以他的貢獻應該是1*2!

1:有零個數比他小,他後面還有乙個數,所以他的貢獻應該是0*1!

4:有三個數比他小,他後面還有0個數,但是1 2 3都在前面出現過,所以他的貢獻應該是0*0!

所以數列5  2  3  1  4的前面有4*4!+1*3!+1*2!+0*1!+0*0!個數列

它本身就是第4*4!+1*3!+1*2!+0*1!+0*0!+1個數列

如何知道比他小的數字的個數,和樹狀陣列維護逆序對的原理一樣,初始時都為1,如果出現過,就-1,求字首和

而階乘我們可以用秦九韶演算法優化,比如上面的式子就=((((4*4+1)*3)+1)*2+0)*1+0*1+1

**:

1 #include 2 #include 3 #include 4

using

namespace

std;

5#define int long long

6const

int maxn=1e6+10,mod=998244353;7

intn;

8int

a[maxn],tmp[maxn],sum[maxn];

9void fix(int x,int

k)12

int query(int

x)17

signed main()

25int ans=tmp[1]*(n-1

);26

for (int i = 2;i <= n-1;i++)

30 ans=ans+1;ans+=ans*tmp[n]*1;ans=ans%mod;

31 printf("

%lld\n

",ans);

32return0;

33 }

洛谷 P5367 模板 康托展開

題目 首先我們要知道康托展開的公式 即 rand a i 1 n i 1 i n rand i 表示i在之前序列中未出現的第幾個 n i 我們可以用o n 的複雜度預處理出來。辣麼rand i 我們怎麼求呢?如果暴力列舉鐵定超時。我們想想可以用什麼來查詢,我們可以用樹狀陣列來查詢 看演算法標籤 in...

luogu P5367 模板 康托展開

傳送門 剛開始背的式子,一測wawawa.式子背錯了.然後請教了下大佬。就考慮比當前排列字典序小的有哪些。第i個位置,後邊剩下n i個位置沒有填,所以 n i 考慮第i個位置,就再乘以 i ask a i ask a i 為再i位置之前出現的比a i 小的數的個數。用樹狀陣列維護 include d...

康托展開 康托逆展開

x a n n 1 a n 1 n 2 a i i 1 a 1 0 其中a i 為當前未出現的元素中是排在第幾個 從0開始 這就是康托展開。康托展開可用 實現。編輯 把乙個整數x展開成如下形式 x a n n 1 a n 1 n 2 a i i 1 a 2 1 a 1 0 其中a i 為當前未出現的...