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

Longest Increasing Subsequence Arrays (组合计数)

2016-07-25 13:21 417 查看

题目:

LINK

题意:一个序列长度为 M, 每个数值在 [1, N], 问这个序列的最长上升子序列刚好

为N 的时候, 序列有多少种。

分析:

感谢kg2006的思路。

首先选取 N 个位置 S1,S2,S3 ….. SN。 设S1 之前的位置没有 1, S1 - S2 没有 2…

则有 S1 之前 S1-S2之间 … SN-1 - SN 之间的数都是有 N-1 中选择方案。 而 SN

之后位置均为 N种。 枚举 SN 的位置 Last, 可以知道

Ans = ∑(Last−1N−1)∗(N−1)Last−N∗NM−Last

Code:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxm = 500000 + 131;
const int maxn = 100000 + 131;
const LL MOD = 1e9 + 7;
LL Mjie[maxm], Inv[maxm], JieInv[maxm];
LL PowN[maxm], PowN_[maxm];

void INIT() {
Mjie[0] = Mjie[1] = 1;
Inv[1] = 1;
for(LL i = 2; i < maxm; ++i) {
Mjie[i] = Mjie[i-1] * i % MOD;
Inv[i] = (MOD - MOD / i) * Inv[MOD % i] % MOD;
}
JieInv[1] = JieInv[0] = 1;
for(LL i = 2; i < maxm; ++i)
JieInv[i] = JieInv[i-1] * Inv[i] % MOD;
}

int main() {
INIT();
int t;
LL m, n;
scanf("%d", &t);
while(t--) {
scanf("%lld%lld", &m, &n);
PowN_[0] = PowN[0] = 1;
for(LL i = 1; i < maxm; ++i) {
PowN[i] = PowN[i-1] * n % MOD;
PowN_[i] = PowN_[i-1] * (n-1) % MOD;
}
LL Ans = 0;
for(LL Last = m; Last >= n; Last--) {
LL temp = (Mjie[Last-1] * JieInv[n-1] % MOD) * JieInv[Last-n] % MOD;
temp = temp * PowN_[Last-n] % MOD;
temp = temp * PowN[m-Last] % MOD;
Ans =( Ans + temp ) % MOD;
}
printf("%lld\n", Ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Hackrank 组合排列