[BZOJ2111][ZJOI2010]排列計數-題解
題目地址-洛谷
題目地址-BZOJ
簡易題意
讓你求所有的排列中滿足的個數。
其實,我們可以發現,對於每個,它必然要有兩個比它小的在和的位置,這個性質就十分像一個大根堆,可以顯然的看出絕對最大。
所以我們把這個排列放在一個大根堆上來看,其實也就是一棵完全二叉樹,每個點的值滿足比它的兩個兒子大,那麼我們考慮當前點,左兒子為,右兒子為,為子樹大小,那麼這個子樹的方案數就相當於,我們相當於在中選一些數出來,放在左右兒子的子樹內,那麼方案數顯然就是,就是在這裡選出個數,然後再乘以在左兒子和右兒子中的方案數就是答案了,所以我們預處理階乘直接遞迴計算即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=2e6+1;
int n;ll Mod;
ll fac[N],inv_fac[N],sze[N];
ll fpow(ll a,ll b){
ll res=1;
for(;b;b>>=1,a=(a*a)%Mod)
if(b&1)res=(res*a)%Mod;
return res;
}
ll C(ll n,ll m){
if(m>n) return 0;
if(m==0||n==m) return 1;
if(n<Mod)return fac[n]*inv_fac[m]%Mod*inv_fac[n-m]%Mod;
return C(n/Mod,m/Mod)*C(n%Mod,m%Mod)%Mod;
}
ll calc(int a){
if(a>n) return 1;
return calc(a<<1)*calc(a<<1|1)%Mod*C(sze[a]-1,sze[a<<1])%Mod;//這裡a<<1可能爆空間,所以開兩倍
}
int main(){
scanf("%d%lld",&n,&Mod);
fac[0]=fac[1]=inv_fac[0]=sze[1]=1;
for(ll i=2;i<=n;i++)
fac[i]=(fac[i-1]*i)%Mod,sze[i]=1;
for(int i=n;i>1;i--)sze[i>>1]+=sze[i];
inv_fac[n]=fpow(fac[n],Mod-2);
for(ll i=n-1;i>=1;i--)
inv_fac[i]=(inv_fac[i+1]*(i+1))%Mod;
printf("%lld\n",calc(1));
return 0;
}
一種更神奇的方法是,原問題相當於求一個二叉樹的拓撲排序數量,直接套公式可得:
還是同樣處理一下子樹大小和逆元階乘即可計算。
原理我也不懂QWQ
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=2e6+1;
ll n,p,s[M],inv[M];
int main()
{
scanf("%lld%lld",&n,&p);
inv[1]=inv[0]=1;
for(ll i=1;i<=n;i++) s[i]=1;
for(ll i=2;i<=n;i++) inv[i]=(p-p/i)*inv[p%i]%p;//線性求逆元
for(ll i=n;i>1;i--) s[i>>1]+=s[i];
ll ans=1;
for(ll i=1;i<=n;i++) ans=ans*i%p*inv[s[i]]%p;
printf("%lld",ans);
return 0;
}
相關文章
- 洛谷 P2606 [ZJOI2010] 排列計數 題解
- BZOJ 2111 [ZJOI2010]Perm 排列計數:Tree dp + Lucas定理
- 洛谷P2606 [ZJOI2010]排列計數(組合數 dp)
- 排列 題解
- 全排列價值(數學問題)
- 遞迴解決全排列問題遞迴
- 數之重排列
- 回溯法解決全排列問題總結
- 回溯法(排列樹)解決八(N)皇后問題
- 【題解】A23329.等差數列計數
- 正方形計數 題解
- 藍橋杯-排列序數
- 南沙陳老師解題重排列1234使得每個數字都在不同原來位置上
- 遞迴-*全排列問題遞迴
- 字串排列組合問題字串
- CF1796C C. Maximum Set 題解 排列組合
- 【POJ 2249】 Binomial Showdown 組合數學 排列組合計算
- 【數學】組合數學 - 排列組合
- 藍橋杯全排列專題
- js陣列全排列問題JS陣列
- acm-(推式子、好題、數學、排列計數)2020ICPC·小米 網路選拔賽第一場 H.GroupingACM
- 數列 題解
- 實現將10個整數升序排列
- 常見規格排列組合問題
- 【力扣】排列問題(回溯法)(去重)力扣
- LeetCode每日一題: 排列硬幣(No.441)LeetCode每日一題
- 回溯問題Python框架總結——排列組合問題Python框架
- 雙模數問題 題解
- #數位DP 計數問題
- 組合數學筆記-排列與組合筆記
- 藍橋杯之帶分數(全排列+暴力)
- 計數題總結
- 怎樣解題|題7.5.12:因數的個數
- 【入門】統計每個月兔子的總數 - 題解
- 用js寫三個數,讓三個數從小到大排列JS
- 逆序排列
- Powershell 重新排列去重 Windows環境變數Windows變數
- 楊輝三角(組合數)+排列組合