Atcoder Grand Contest 024E Sequence Growing Hard

5 篇文章 0 订阅

题目在这里呀!
啊啊啊准备了一个月期末考的我终于飘回来啦~~
真可谓在学OI的时候忘不了文化课,然后在学文化课的时候又想念编程啦qwq

那那那开始我的七月第一篇题解?
(我七月想写很多很多题解的w)


题意

考虑 N +1 个数组 {A0,A1,…,AN}。
其中 Ai 的长度是 i,Ai 内的所有数字都在 1 到 K 之间。 Ai−1 是 Ai 的子序列,即 Ai 删一个数字可以得到 Ai−1。 Ai 的字典序大于 Ai−1。
输入 N,K,M 问序列个数模 M。

题解

好像有两种方法?
反倒我还没理解那个好理解的方法,以后补全吧
很容易想到dp吧。
那么那么
考虑每次从前面那个状态插入一个数,那么插入位置右边的那个数要严格小于插入的数。
所以我们去想想状态
fi,j,p f i , j , p 表示当前长度为i,取到数字j,有p个位置可插的方案数。
那么考虑转移,
一种情况,不插在这个位置,那么 fi,j,p1 f i , j , p − 1 += fi,j,p f i , j , p
还有就是插在这个位置,那么 fi+1,j,p f i + 1 , j , p += fi,j,p f i , j , p
或者这个数字不插了, fi,j+1,i f i , j + 1 , i += fi,j,p f i , j , p 第三维为i是因为j加1了所以所有数字都比它小。
答案就是 fn,k+1,n f n , k + 1 , n

然后…就好了?代填坑(另一种方法)

//Suplex
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n,k,m;
long long f[333][333][333];

int main()
{
    scanf("%d%d%d",&n,&k,&m);
    f[0][1][0]=1;
    for(int i=0;i<=n;i++)
        for(int j=1;j<=k;j++)
            for(int p=i;p>=0;p--){
                if(p) (f[i][j][p-1]+=f[i][j][p]) %= m;
                else (f[i][j+1][i]+=f[i][j][p]) %= m;
                (f[i+1][j][p]+=f[i][j][p]*(p+1)) %= m;
            }
    printf("%lld\n",f[n][k+1][n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值