UVa1485/LA5092 Permutation Counting

题目链接

        本题是2010年ICPC 亚洲区域赛 哈尔滨赛区的题目

题意

        给定 1~n 的排列{a1, a2, …, an},满足ai>i 的下标i 的个数称为此排列的E 值。例如{1,3,2,4}的E 值为1,{4, 3, 2, 1}的E 值为2。给定整数n 和k(1≤n≤1 000,0≤k≤n),求E 值恰好为k 的排列个数。

分析

        递推求解,用f[n][k]表示递推状态,对问题做适当转化可构建出递推式。

        若排列的1号位放的数正好是1,则转化成了f[n-1][k]。接下来考虑1也参与交换对结果的变化:若1和某个ai>i的元素交换,则转化成了新的排列但计数结果仍然f[n-1][k],当ai>i的元素有k个时有k种交换选择;若1和某个ai≤i的元素交换,则新排列的1号位新增一个ai>i的元素,当ai>i的元素有k-1个时有n-k种交换选择。

        至此,可以得出递推式:f[n][k] = f[n-1][k] + k*f[n-1][k] + (n-k)*f[n-1][k-1]

                                                          = (k+1)*f[n-1][k] + (n-k)*f[n-1][k-1]

AC代码


#include <iostream>
using namespace std;

#define M 1000000007
#define N 10002
int f[N][N>>1], n, k;

int solve() {
    return k >= n ? 0 : ((k<<1) < n ? f[n][k] : f[n][n-1-k]);
}

int main() {
    for (long long n=1; n<N; ++n) {
        f[n][0] = 1;
        for (long long k=1, m=(n-1)>>1; k<=m; ++k)
            f[n][k] = ((f[n-1][(k<<1) < n-1 ? k : k-1])*(k+1) + f[n-1][k-1]*(n-k)) % M;
    }
    while (cin >> n >> k) cout << solve() << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值