舉個栗子大家應該就能懂了:
我現在生成了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 4using
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 為當前未出現的...