题解:P9102 [PA2020] Cukierki

一道 dp 题。

Solution P9102

Idea

我们对 aa 数组升序排序。

dpi,jdp_{i,j} 为前 ii 个数,保证 11jj 区间内所有的数能够全部被包含的方案数。

那么转移就是 dpi,j=dpi1,j+dpi1,jaidp_{i,j}=dp_{i-1,j}+dp_{i-1,j-a_i}。原因也十分简单:选与不选求和。注意转移时不可以让下标越界

第一维可以滚掉。

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5005,mod=1000000007;
int a[N],n;
ll dp[N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	dp[0]=1;
	for(int i=1;i<=n;i++){
		for(int j=N-5;j>=a[i]-1;j--){
			(dp[min(a[i]+j,N-5)]+=dp[j])%=mod;
		}
	}
	ll ans=0;
	for(int i=1;i<=N-5;i++)ans=(ans+dp[i])%mod;
	printf("%lld",ans);
	return 0;
}

Tip

为什么要升序排序?假如不排序,如果在一次转移中,dpk=dpk+dpjdp_k=dp_k+dp_j,但是 dpjdp_j 还未被转移完,转移就是错误的。

可以用

3
1 2 1

手搓一下。

posted @ 2024-11-26 17:01  Weslie_qwq  阅读(19)  评论(0)    收藏  举报  来源