1 条题解

  • 0
    @ 2025-8-24 22:26:21

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar panyf
    **

    搬运于2025-08-24 22:26:21,当前版本为作者最后更新于2020-11-13 14:23:08,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    DP。

    fi,j,k,lf_{i,j,k,l} 表示做第 ii 个烤肉串,用了 jj 秒,做了 kk 次梦,离可以做梦还有 ll 秒的方案数。

    转移方程(注意 t=0t=0 的情况):

    fi,j,k,0=fi,j1,k,1+fi,j1,k,0f_{i,j,k,0}=f_{i,j-1,k,1}+f_{i,j-1,k,0} fi,j,k,t=fi,j1,k1,0f_{i,j,k,t}=f_{i,j-1,k-1,0} fi,j,k,l=fi,j1,k,l+1(0<l<t)f_{i,j,k,l}=f_{i,j-1,k,l+1}(0<l<t)

    时间复杂度 O(nq2t)O(nq^2t),不能通过。

    注意到 kqt+1k\leq\left\lceil\dfrac{q}{t+1}\right\rceil,缩小枚举上界,时间复杂度优化到 O(nq2)O(nq^2)

    前两维可以滚掉,空间复杂度 O(qt)O(qt)

    为了减少边界特判,代码中的 kk 表示做了 k1k-1 次梦。

    #include<bits/stdc++.h>
    using namespace std;
    const int P=1e9+7;
    int f[259][109];
    int main(){
    	int n,m,t,q,x,i,j,k,l;
    	scanf("%d%d",&n,&t),f[1][0]=1;
    	for(i=1;i<=n;++i){
    		scanf("%d%d",&q,&x),m=min(q-x+1,q/(t+1)+2);
    		for(j=1;j<=q;++j){
    			for(k=m;k;--k){
    				if(t)f[k][0]=(f[k][1]+f[k][0])%P;
    				else f[k][0]=(f[k][0]+f[k-1][0])%P;
    				for(l=1;l<t;++l)f[k][l]=f[k][l+1];
    				if(t)f[k][t]=f[k-1][0];
    			}
    		}
    		for(k=2;k<=m;++k)for(l=0;l<=t;++l)f[1][l]=(f[1][l]+f[k][l])%P,f[k][l]=0;
    	}
    	for(x=l=0;l<=t;++l)x=(x+f[1][l])%P;
    	printf("%d",x);
    	return 0;
    }
    
    • 1

    信息

    ID
    6224
    时间
    2000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者