[DP] Codeforces #626F. Group Projects

显然是 DP 。这种贡献和最值有关的,一般用按顺序插入的方法 DP ,会简单很多。有挺多类似的题的。
这题就是 fi,j,k 表示插入了前 i 个,有 j 个块开发待插入,总代价为 k
每次插入 i+1 就考虑是新开一个块还是插入原有块中,是否要闭合块。转移 O(1)
有个问题就是一个块的贡献是延迟计算的,即闭合后才会确定贡献。 k 应该记什么呢?
比较直接的想法就是新开块时ai,闭合时 +ai ,但是发现这样会导致 k 取值范围大,状态数就炸了。
所以我们应该假设当前的 ai 是每个块的最大值, i 增大时加上 (ai+1ai)j 就好了。
总体来说比较套路吧。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=205,maxk=1005,MOD=1e9+7;
typedef long long LL;
int n,K,a[maxn];
LL f[2][maxn][maxk],ans; 
int main(){
    freopen("cf626F.in","r",stdin);
    freopen("cf626F.out","w",stdout);
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    f[0][0][0]=1; a[0]=a[1]; 
    for(int i=0;i<=n-1;i++){
        memset(f[(i&1)^1],0,sizeof(f[(i&1)^1]));  
        for(int j=0;j<=i;j++)
         for(int k=0;k<=K;k++) if(f[i&1][j][k]&&k+j*(a[i+1]-a[i])<=K){
            (f[(i&1)^1][j+1][k+j*(a[i+1]-a[i])]+=f[i&1][j][k])%=MOD; //新  
            (f[(i&1)^1][j][k+j*(a[i+1]-a[i])]+=f[i&1][j][k])%=MOD; //新 闭 
            if(j) (f[(i&1)^1][j][k+j*(a[i+1]-a[i])]+=f[i&1][j][k]*j%MOD)%=MOD; // 插入  
            if(j) (f[(i&1)^1][j-1][k+j*(a[i+1]-a[i])]+=f[i&1][j][k]*j%MOD)%=MOD; // 插入 闭 
         }      
    }

    for(int i=0;i<=K;i++) ans=(ans+f[n&1][0][i])%MOD;
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值