20180516模拟赛T3——bag

Posted pfy_pfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20180516模拟赛T3——bag相关的知识,希望对你有一定的参考价值。

技术分享图片

技术分享图片

题解

Cqz大佬在代码上的注释:

前i个物品,做成体积为j的东西,有多少种方案数

后i个物品,做成体积为j的东西,有多少种方案书(大佬打错了)

两个DP数组合并。 做不到?

其实就是把中间那段切断,然后把左右两边合并。

技术分享图片

贴一段代码吧:

Rep(i,1,n)
{
    Dep(j,m,v[i])
        f[i][j] = (f[i-1][j] + f[i-1][j - v[i]])%Mod;
    Dep(j,v[i]-1,0)
        f[i][j] = f[i-1][j];
}
g[n+1][0] = 1;
Dep(i,n,1)
{
    Dep(j,m,v[i])
        g[i][j] = (g[i+1][j] + g[i+1][j - v[i]])%Mod;
    Dep(j,v[i]-1,0)
        g[i][j] = g[i+1][j];
}
Rep(i,1,n)
{
    ll ans = 0;
    Rep(j,0,m)
        ans = (ans + (1ll * f[i-1][j] * g[i+1][m-j] % Mod)) % Mod;//注意合并阶段一定要开long long
    writeln(ans);
}

zd大佬&sxd大佬的做法

先跑一遍01背包,要删除一段时,倒着跑一遍。请教了两位大佬,然而好像都无法证明。但在感性上应该是可以理解的(极其具有对称性)。

这个的代码就简单多了:

dp[0] = 1;
for(int i = 1; i <= n; ++i)
    for(int j = m; j >= v[i]; --j)
        dp[j] = (dp[j]+dp[j-v[i]])%mod;
for(int i = 1; i <= n; ++i)
{
    for(int j = 0; j <= m; ++j)
        f[j] = dp[j];
    for(int j = v[i]; j <= m; ++j)
        f[j] = ((f[j]-f[j-v[i]])%mod+mod)%mod;
    writeln(f[m]);
}

听说yyh大佬有一种容斥做法,然而我看不懂啊……只好直接贴代码了:

f[0]=1;
for(LL i=1; i<=n; i++)
{
    a[i]=read();
    for(LL j=m; j>=a[i]; j--)
        (f[j]+=f[j-a[i]])%=md;
}
for(LL i=1; i<=n; i++)
{
    ans=f[m];
    for(LL j=1; j*a[i]<=m; j++)
    {
        if(j&1)
            (ans-=f[m-j*a[i]])%=md;
        else
            (ans+=f[m-j*a[i]])%=md;
    }
    printf("%lld\n",(ans%md+md)%md);
}

以上是关于20180516模拟赛T3——bag的主要内容,如果未能解决你的问题,请参考以下文章

csp-s模拟测试101的T3代码+注释

ztz11的noip模拟赛T3:评分系统

php 20180516 hoverをjQで制御

20180516早课记录11-Linux

javascript 20180516谷歌地图をレスポンシブ対にに

php 20180516タブ切り替え内のマッチハイト