客挑战赛46 C题

排列

https://ac.nowcoder.com/acm/contest/9510/C

牛客挑战赛46 C题
题解:f[i][k][j]表示前i个k个逆序对且最大数的位置在j处的数目,第一维需要用滚动数组优化,但是求f[i][k][j]的时候会发现需要对前i-1长度排列的最大数的位置进行枚举,这一层可以用以个sum[i][k][j]优化,sum[i][k][j]表示长度为i的排列最大数的位置从1到j并且超级逆序对为k的个数总和

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=2e6+10;
const LL mod=998244353;
LL n,K;
LL f[3][505][505];
LL sum[3][505][505];
LL ksm(LL x,LL N)
{
    LL ans=1;
    LL tmp=x%mod;
    while(N){
        if(N&1){
            ans*=tmp;
            ans%=mod;
        }
        tmp*=tmp;
        tmp%=mod;
        N/=2;
    }
    return ans;
}
int main()
{
    scanf("%lld%lld",&n,&K);
    memset(f,0,sizeof(f));
    memset(sum,0,sizeof(sum));
    f[1][0][1]=1;
    sum[1][0][1]=1;
    LL pre=2;
    for(register LL i=2;i<=n;++i){
         for(register LL k=0;k<=K;++k){
            for(register LL j=1;j<=i-1;++j){
                f[pre][k][j]=0;
                if(k-(i-j-1)>=0){
                    f[pre][k][j]=sum[pre^3][k-(i-j-1)][i-1]-sum[pre^3][k-(i-j-1)][j-1];
                    f[pre][k][j]%=mod;
                    f[pre][k][j]=(f[pre][k][j]+mod)%mod;
                }
                if(k-(i-j)>=0){
                    f[pre][k][j]+=sum[pre^3][k-(i-j)][j-1];
                    f[pre][k][j]%=mod;
                }
                sum[pre][k][j]=sum[pre][k][j-1]+f[pre][k][j];
                sum[pre][k][j]%=mod;
           }
           f[pre][k][i]=sum[pre^3][k][i-1];
           sum[pre][k][i]=sum[pre][k][i-1]+f[pre][k][i];
           sum[pre][k][i]%=mod;
        }
        pre^=3;
      }
    if(n%2){
        pre=1;
    }
    else{
        pre=2;
    }
    LL ans=0;
    for(register LL i=1;i<=n;++i){
        ans+=f[pre][K][i];
        ans%=mod;
    }
    printf("%lld\n",ksm(ans,mod-2));
    return 0;
}
全部评论

相关推荐

11-18 09:44
Java
小白也想要offer:简历别放洋屁,搞不还还放错了,当然你投外企除外,以上纯属个人观点
点赞 评论 收藏
分享
Natrium_:这时间我以为飞机票
点赞 评论 收藏
分享
4 收藏 评论
分享
牛客网
牛客企业服务