昨天
對着
題解
看了好久
也沒看懂
那個n!是要幹什麼
題解大概是這樣
雖然還是沒懂這個公式是什麼意思,但是我知道爲什麼答案是了,手動狗頭
逆元打表的代碼
void inverse(ll n, ll mod) {
inv[1] = 1;
for (int i=2; i<=n; ++i) {
inv[i] = (ll) (mod - mod / i) * inv[mod%i] % mod;
}
}
思路:
1.學習了一下笛卡爾樹
笛卡爾樹就是一棵樹,樹上的每個節點代表序列中的一個位置。
中序遍歷即得原序列
子樹中的所有節點的值均大於(小於)根節點
對於一個序列可以O(n)建樹
2.發現A序列和B序列RMQ similar就是A序列和B序列的笛卡爾樹長的一樣
3.計算一個序列和A序列笛卡爾樹一樣的概率乘以n/2
概率的計算就是每個節點的子樹節點個數的倒數相乘,即當前節點在這個遞歸的區間裏是最大值的概率
建笛卡爾樹的代碼
void build(){
go(i,1,n){
scanf("%d",&a[i]); ls[i]=rs[i]=0;
if (a[i]<=a[stk[top]]||top==0){
rs[stk[top]]=i;
fa[i]=stk[top];
stk[++top]=i;
}
else{
while (a[stk[top]]<a[i]&&top>=1) top--;
rs[stk[top]]=i;
fa[i]=stk[top];
ls[i]=stk[top+1];
fa[stk[top+1]]=i;
stk[++top]=i;
}
}
}
本題AC代碼
#include<iostream>
#include<algorithm>
#include<stack>
#include<string.h>
#define go(i,a,b) for (int i=a;i<=b;i++)
#define N 1000005
#define MOD 1000000007
#define ll long long
using namespace std;
int stk[N],top,rs[N],ls[N],fa[N],a[N];
ll ans,inv[N];
void inverse(ll n, ll mod) {
inv[1] = 1;
for (int i=2; i<=n; ++i) {
inv[i] = (ll) (mod - mod / i) * inv[mod%i] % mod;
}
}
ll dfs(ll u){
if (!rs[u]&&!ls[u]) return 1;
int tot=0;
if (rs[u]) tot+=dfs(rs[u]);
if (ls[u]) tot+=dfs(ls[u]);
tot++;
ans=ans*inv[tot]%MOD;
return tot;
}
ll mod(ll x){
while (x>=MOD) x-=MOD;
return x;
}
int main(){
inverse(N-5,MOD);
int T,n;
scanf("%d",&T);
while (T--){
scanf("%d",&n);
top=0;
ans=1;
go(i,1,n){
scanf("%d",&a[i]); ls[i]=rs[i]=0;
if (a[i]<=a[stk[top]]||top==0){
rs[stk[top]]=i;
fa[i]=stk[top];
stk[++top]=i;
}
else{
while (a[stk[top]]<a[i]&&top>=1) top--;
rs[stk[top]]=i;
fa[i]=stk[top];
ls[i]=stk[top+1];
fa[stk[top+1]]=i;
stk[++top]=i;
}
}
go(i,1,n) if (fa[i]==0) dfs(i);
ans=ans*inv[2]%MOD*n%MOD;
cout<<ans<<endl;
}
return 0;
}
剛開始ls和rs寫了兩個memset,實力TLE,改成for循環賦值過了。