zoukankan      html  css  js  c++  java
  • CF626F Group Projects

    发现直接做非常困难,考虑将能力值排序然后从小到大插入。

    (f_{i,j,l}) 表示前 (i) 个人,有 (j) 组需要继续加人,不和谐度之和至少(l) 的方案数。此时加入一个人产生的贡献为 (t=j imes(a_{i+1}-a_i))。分三种情况转移:

    • 组数加一,即第 (i+1) 个人在一个新的组中,然后该组还需要继续加人。

      [f_{i+1,j+1,l+t}gets f_{i+1,j+1,l+t}+f_{i,j,l} ]

    • 组数不变,第 (i+1) 个人在一个新的组中,然后该组不需要继续加人,或加入了一个原有的组,然后该组还需要继续加人。

      [f_{i+1,j,l+t}gets f_{i+1,j,l+t}+f_{i,j,l} imes(j+1) ]

    • 组数减一,即第 (i+1) 个人加入了一个原有的组,然后该组不需要继续加人。

      [f_{i+1,j-1,l+t}gets f_{i+1,j-1,l+t}+j imes f_{i,j,l} ]

    最后的答案就是 (sumlimits_{l=0}^k f_{n,0,l})

    其实这道题无论是预处理还是 DP 部分和 JOI2012 的袋鼠都十分相似,都是通过排序来确定每次产生的贡献(变化),状态都是记录遗留下来需要继续做的量。

    时间复杂度 (O(n^2k))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 205
    #define Mod 1000000007
    #define For(i,x,y)for(i=x;i<=(y);i++)
    int f[N][N][1005],a[N];
    int main()
    {
    	int n,k,i,j,l,ans=0,t;
    	cin>>n>>k;
    	For(i,1,n)cin>>a[i];
    	sort(a+1,a+n+1);
    	f[0][0][0]=1;
    	For(i,0,n-1)
    	For(j,0,i)
    	For(l,0,k)
    	{
    		t=l+j*(a[i+1]-a[i]);
    		if(t<=k)
    		{
    			f[i+1][j+1][t]=(f[i+1][j+1][t]+f[i][j][l])%Mod;
    			//作为一组的开头 
    			f[i+1][j][t]=(f[i+1][j][t]+1LL*f[i][j][l]*(j+1))%Mod;
    			//单独作为一组或接到一组后面 
    			if(j)f[i+1][j-1][t]=(f[i+1][j-1][t]+1LL*j*f[i][j][l])%Mod;
    			//作为一组的末尾 
    		}
    		else break;
    	}
    	For(l,0,k)ans=(ans+f[n][0][l])%Mod;
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    python类方法和静态方法
    42个创意户外广告设计
    50免费为移动设计和开发的PSD文件极力推荐
    40个高品质的免费商业PSD文件
    10 个有用免费 CSS3 强大工具
    10个方便的在线CSS代码生成器,网页设计师必备!
    对makefile中,变量定义中 通配符的理解
    GNU make manual 翻译(八十七)
    GNU make manual 翻译(八十九)
    GNU make manual 翻译(八十五)
  • 原文地址:https://www.cnblogs.com/May-2nd/p/13364958.html
Copyright © 2011-2022 走看看