【JZOJ5066】【GDOI2017第二轮模拟day2】中位数

来源:互联网 发布:多益网络二笔试题 编辑:程序博客网 时间:2024/04/28 11:53

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

我们发现:设>=k的数为1,< k的数为-1,我们从中间枚举序列选的情况:当当前序列满足-1,1交替出现且对称时,这时下一个放的数打破了-1,1交替出现的情况,那么假如连续的数是1时,答案则为1,否则为0。(口头解释有点难,还是建议读者自己手玩一下!)
这里写图片描述
那么设f[i]表示从中间开始长度为2*i-1的满足-1,1交替出现且对称序列的数量,的用组合数算一下我们就可一知道答案>=k的方案,在算一下答案>=k+1的方案,相减即可。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const ll maxn=1e6,mo=998244353;ll f[maxn+5][2],c[maxn+5];ll n,m,i,t,j,k,l,x,y,z,ans;ll make(ll x){    return x*(x-1)%mo;}ll dg(ll m){    ll ans=0;memset(f,0,sizeof(f));    f[1][0]=m-1,f[1][1]=n-m+1;    for (i=1;i<n/2+1;i++){        t=(i+1)/2*2;k=(i+1)*2-1-t;        if (i%2){            if (t<=m-1) f[i+1][1]=f[i][1]*make(m+1-t)%mo,ans+=((n-m+1-k)%mo*c[n-i*2]*2%mo-make(n-m+1-k)*c[n-i*2-1]%mo+mo)%mo*f[i][1]%mo;            else ans+=f[i][1]*c[n-i*2+1]%mo;            if(t<=n-m+1) f[i+1][0]=f[i][0]*make(n-m+3-t)%mo;        }        if (i%2==0){            if (k<=m-1) f[i+1][0]=f[i][0]*make(m+1-k)%mo,ans+=((n-m+1-t)%mo*c[n-i*2]*2%mo-make(n-m+1-t)*c[n-i*2-1]%mo+mo)%mo*f[i][0]%mo;            else ans+=f[i][0]*c[n-i*2+1]%mo;            if (k<=n-m+1) f[i+1][1]=f[i][1]*make(n-m+3-k)%mo;        }    }    if ((n/2+1)%2==0)ans+=f[n/2+1][0];    else ans+=f[n/2+1][1];    ans%=mo;    return ans;}int main(){    freopen("median.in","r",stdin);freopen("median.out","w",stdout);    scanf("%lld%lld",&n,&m);c[0]=1;    for (i=1;i<=n;i++)c[i]=c[i-1]*i%mo;    ans=(dg(m)-dg(m+1)+mo)%mo;    printf("%lld\n",ans);}
0 0
原创粉丝点击