您的位置:首页 > 产品设计 > UI/UE

Queue of Soldiers

2016-09-14 23:11 357 查看

Queue of Soldiers



题意:士兵过山洞在第i个人之后,后面比i高的人都会被杀死,问如果要杀死k个人,有几种排队方法。

解法:dp,首先排序离散化,然后f[i][j]表示i高度一共死了j人,推到f[i+1][j+q] : 到第 i+1 这个身高段,死了 j+q个人。明显除了插入第一位,其他位置都会死亡,于是就是排列组合了。

f[i+1][j+q] = ∑ f[i][j] * C(sum[i] + q - 1,q) (C表示求组合数)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include <string.h>
using namespace std;

#define LL long long
const int maxn = 150;
const int MOD = 1000000007;
LL cnt[52001], a[60000], f[maxn][2000], pre[52001], sum[52001], inve[52001];
int n, m, tot;

LL pow_mod(LL a, LL n) {
a%=MOD;
LL ret=1;
while (n) {
if (n&1) ret=(ret*a)%MOD;
a=(a*a)%MOD;
n>>=1;
}
return ret;
}

LL inv(LL a, LL mod) {
return pow_mod(a, mod-2);
}

void init() {
memset(pre, 0, sizeof(pre));
memset(inve, 0, sizeof(inve));
pre[0] = 1;
for (int i = 1; i <= 52000; i++) pre[i] = (pre[i-1]*i)%MOD;
for (int i = 0; i <= 52000; i++) inve[i] = inv(pre[i], MOD);
}

LL C(LL y, LL x) {
if (x <= 1 || y == 0) return 1;
LL t = pre[x];
t = t*inve[y]%MOD*inve[x-y]%MOD;
return t;
}

int main() {

init();

int tt;
scanf("%d", &tt);
for (int cases = 1; cases <= tt; cases++) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
sort(a+1, a+n+1);
a[0] = 0;
tot = 0;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; i++) {
if (a[i] != a[i-1]) tot++;
cnt[tot]++;
}
sum[0] = 0;
for (int i = 1; i <= tot; i++) sum[i] = sum[i-1]+cnt[i];
//f[i][j];
memset(f, 0, sizeof(f));
f[1][0] = 1;
for (int i = 1; i < tot; i++) {
for (int j = 0; j <= m; j++) if (f[i][j] != 0) {
for (int q = 0; q <= cnt[i+1]; q++) {
if (j+q > m || q > cnt[i+1]) break;
f[i+1][j+q] = (f[i+1][j+q]+f[i][j]*C(q, sum[i]+q-1)%MOD)%MOD;
}
}
}
printf("Case %d: %lld\n", cases, f[tot][m]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: