牛客小白月赛23f美丽的序列I,数学+分类
美丽的序列I
https://ac.nowcoder.com/acm/contest/4784/F
一个不降序列本身度是1,要分成若干不降,那么每降的地方就分割一次,所以就转变成求序列有多少前>后——分割次数
一个确定数列的美丽度=1+分割次数
1是每个数列都要加的,分割次数不确定(可能为0)
所有的1的和=可以排成的数列方案数
分割次数和=(遍历每两个相邻数)ai>ai+1的组合数*贡献(即不考虑这两个位置,其他位置的组合数)
前的情况大概怎么几种
情况-1,-2是没有前<后的
特别注意情况1和2是不同的
2中6有5种方法,5只有4种方法
先算斜阴影,
再算竖阴影,因为是点的方法连续递增1,所以(最大+最少)*数量 求和
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7,N=1e5+10; ll n,inv2,l[N],r[N],pro[N],repro[N],pl,pr,el,er,ans,big,small,num; ll qmi(ll a,ll b,ll mod){ ll ans=1; while(b){ if(b&1) ans=ans*a%mod; b>>=1; a=a*a%mod; } return ans; } int main(){ cin>>n; inv2=qmi(2,mod-2,mod); for(int i=1;i<=n;i++){ cin>>l[i]>>r[i]; } pro[0]=1; for(int i=1;i<=n;i++) pro[i]=pro[i-1]*(r[i]-l[i]+1)%mod; repro[n+1]=1; for(int i=n;i>=1;i--) repro[i]=repro[i+1]*(r[i]-l[i]+1)%mod; ans=pro[n]; for(int i=2;i<=n;i++){ pl=l[i-1], pr=r[i-1]; el=l[i], er=r[i]; if(pr<=el) continue; if(pl>er){//情况1 ans=(ans+(er-el+1)*(pr-pl+1)%mod*pro[i-2]%mod*repro[i+1]%mod)%mod; continue; } if(pr>er){//斜阴影 ans=(ans+(pr-er)*(er-el+1)%mod*pro[i-2]%mod*repro[i+1]%mod)%mod; pr=er; } //竖阴影 big=pr-el; small=max(pl-el,0LL); num=big-small+1; ans=(ans+(big+small)*num%mod*inv2%mod*pro[i-2]%mod*repro[i+1]%mod)%mod; } cout<<ans; return 0; }
创作不易