zoukankan      html  css  js  c++  java
  • 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
    ",(ans%md+md)%md);
    }
    
  • 相关阅读:
    收集珠子
    压缩变换(程序设计)
    动态规划-树上dp-1757. 搜集钻石
    动态规划-1620. 收集硬币
    动态规划-状态压缩-707. 最优账户结余
    图-1400. 图的费马点
    数学-快速幂
    计算几何-5361. 圆和矩形是否有重叠
    图-搜索-dfs-739. 24点
    图-dfs-连通分量-旋转变换-804. 不同岛屿的数量II
  • 原文地址:https://www.cnblogs.com/pfypfy/p/9048088.html
Copyright © 2011-2022 走看看