题目链接
题意:DRD具有分身的能力,对于两个分身A和B来说,如果A的各个能力都强于B,那么B就无法生存(其实就是每个有一个n维向量,每个人相比于其他必须有一个突出大的,比如2,1 和 1 ,1 就不能共存)先给定DRD的n~2000种能力的上限值,上限值的和sum_t~2000,问最多有多少个克隆人可以共存,结果MOD 1E7;
题解:重点是考虑两个互相共存的东西,比如1,2 和 2 ,1 就比较好,还可以1,2 和2,0, 但是原来的可以加上3,0 后来的就不行,所以发现这样:第一,和相同的一定可以共存,交错的感觉。第二,和不相同的一定没必要共存,因为都可以对应一个替换。转换成为所有能力值和是多少的时候个数最多,本来是dp可以算的,但是因为要MOD 1E7,猜想是所有上限的和的一半最大,正态分布呗。。。或者这样想,能力和为一半,那么交错的可能性就大了。另外本题算个数,不能用2进制的多重背包来写。
重点:分析交错出现的情况,发现出特例,找出规律,往简单可做上猜想简化。想到凑出上限和的一半。另外有一种更快的写算多重背包情况数的方法。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const int maxn = 2e3 + 100;<span style="font-family: Arial, Helvetica, sans-serif;">//代码很简单</span>
const int MOD = 1e9 + 7;
int dp[maxn], t[maxn], n;
int tot;
void zeroP(int k)//没有用。。。因为不能这样写,会有重复的,因为不是完美的2进制分割。
{
for(int i = tot;i >= k;i--)
{
int j = i - k;
dp[i] = (dp[i] + dp[j])%MOD;
}
}
void getDp()
{
memset(dp, 0, sizeof(dp));
dp[0] = 1;
REP_D(i, 1, n)//最笨的多重背包。
{
for(int j = tot;j >= 0;j--)
{
for(int k = 1;k <= t[i];k++)
{
if(j >= k)
dp[j] = (dp[j] + dp[j - k])%MOD;
}
}
}
}
void solve()
{
getDp();
printf("%d\n", dp[tot]);
}
int main()
{
// freopen("1Ain.txt", "r", stdin);
//freopen("1Aout.txt", "w", stdout);
int ncase;
scanf("%d", &ncase);
while(ncase--)
{
scanf("%d", &n);
tot = 0;
REP_D(i, 1, n)
{
scanf("%d", &t[i]);
tot += t[i];
}
tot /= 2;//关键重点!!!!
solve();
}
return 0;
}
本文探讨了DRD具有分身能力时,如何通过分析能力上限和和值来确定最多能有多少个克隆人共存,重点在于理解交错共存的情况和优化策略,最终通过简化思路得出关键结论。

1022

被折叠的 条评论
为什么被折叠?



