T1.gift
有约束的背包。
先把原序列排序,从小到大,对于其中第x个元素,我们假设它是最小的没有被选的物品,那么小于a[x]的都要被强制选择。
这就会影响统计答案的区间,变成( m-s[i-1],m-s[i] ]。
其余正常转移即可。
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; const int MAXN=1005; const int MOD=1e9+7; int f[MAXN]; int a[MAXN],s[MAXN]; int n,m,ans; int main(){ cin>>n>>m; f[0]=1; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+1+n); for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]; for(int i=n;i>=1;i--){ for(int j=m-s[i-1];j>=0&&j>m-s[i];j--)(ans+=f[j])%=MOD; for(int j=m;j>=a[i];j--)(f[j]+=f[j-a[i]])%=MOD; } if(s[n]<=m) ans++; cout<<ans%MOD; return 0; }
T2.fseq
求概率,想到分母肯定是C(n+m,n),可是分子呢。。
把+1看成向右走,-1看成向上走,就是在一个N*M的网格图中从原点走到(N,M)的方案数了,这是一个不降路径问题 ,答案为C(n+m,n)
可是这里说任意前缀和不能小于0,所以我们可以形象化这个约束条件,也就是不穿过对角线,神奇的卡特兰数来了。
(C(n+m,n)-C(n+m,n-1))/C(n+m,n)
化简以后就是1-m/(n+1)
代码实现,注意m>n的情况要特判。