1 条题解
-
0
一个比较常规的思路,考虑每对 对答案的贡献。
先考虑 的方案数。
显然,设 排序后的序列为 ,然后考虑总方案就是, 表示 的排名:
然后考虑一对 。
如果 。
由于 ,所以 的部分可以无视。
那么对应的方案数就是
$$\frac{tot(a_i-id_i)}{2(a_j-id_j+1)}\times \prod_{k=i+1}^{j-1} \frac {b_k-id_k}{b_k-id_k+1} $$解释一下这个式子,左边的部分是因为 和 是对称的,可以总方案除以二。
如果 那么会导致中间那些数的选择方案书减少一。
如果 。
由于实际上就是与上面的情况相反,那么方案数就是:
$$tot-\frac{tot(a_i-id_i)}{2(a_j-id_j+1)}\times \prod_{k=i+1}^{j-1} \frac {b_k-id_k}{b_k-id_k+1} $$然后考虑维护上面这个东西。
从小到大做,插入到线段树里,右边部分就是全局乘,左边的直接维护就好了。
代码
#include<bits/stdc++.h> #define mid (l+r>>1) #define lid p<<1,l,mid #define rid p<<1|1,mid+1,r #define seg int p,int l,int r using namespace std; const int mod=1e9+7,N=2e5+5; struct hzy{int id,x;}a[N]; struct segtree{int sum1,sum2,la;}tr[N<<2]; int kuai(int a,int b){ int ans=1; for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod; return ans; } void pd(seg){ tr[p<<1].sum1=1ll*tr[p<<1].sum1*tr[p].la%mod; tr[p<<1|1].sum1=1ll*tr[p<<1|1].sum1*tr[p].la%mod; tr[p<<1].la=1ll*tr[p<<1].la*tr[p].la%mod; tr[p<<1|1].la=1ll*tr[p<<1|1].la*tr[p].la%mod; tr[p].la=1; } int ask1(seg,int L,int R){ if(l>=L&&r<=R)return tr[p].sum1; if(tr[p].la!=1)pd(p,l,r); return ((L<=mid?ask1(lid,L,R):0)+(R>mid?ask1(rid,L,R):0))%mod; } int ask2(seg,int L,int R){ if(l>=L&&r<=R)return tr[p].sum2; if(tr[p].la!=1)pd(p,l,r); return ((L<=mid?ask2(lid,L,R):0)+(R>mid?ask2(rid,L,R):0))%mod; } void add(seg,int x,int z){ if(l==r){tr[p].sum1=z,tr[p].sum2=1;return;} if(tr[p].la!=1)pd(p,l,r); if(x<=mid)add(lid,x,z); else add(rid,x,z); tr[p].sum1=(tr[p<<1].sum1+tr[p<<1|1].sum1)%mod; tr[p].sum2=tr[p<<1].sum2+tr[p<<1|1].sum2; } int n,tot=1,ans; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i; for(int i=1;i<=4*n;i++)tr[i].la=1; sort(a+1,a+n+1,[](hzy a,hzy b){return a.x<b.x;}); for(int i=1;i<=n;i++)tot=1ll*tot*(a[i].x-i+1)%mod; if(!tot)return puts("0"),0; int Inv2=kuai(2,mod-2); for(int i=1;i<=n;i++){ int l=ask1(1,1,n,1,a[i].id),r=ask1(1,1,n,a[i].id,n),R=ask2(1,1,n,a[i].id,n),Inv=kuai(a[i].x-i+1,mod-2); ans=(((ans+1ll*l*Inv%mod)%mod+1ll*R*tot%mod)%mod-1ll*r*Inv%mod+mod)%mod; tr[1].la=1ll*tr[1].la*(a[i].x-i)%mod*Inv%mod; add(1,1,n,a[i].id,1ll*tot*Inv2%mod*(a[i].x-i)%mod); } printf("%d",ans); }
- 1
信息
- ID
- 75
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者