码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3664 Permutation Counting (DP)

时间:2016-08-16 21:37:25      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

题意:给一个 n,求在 n 的所有排列中,恰好有 k 个数a[i] > i 的个数。

析:很明显是DP,搞了好久才搞出来,觉得自己DP,实在是太low了,思路是这样的。

dp[i][j]表示 i 个排列,恰好有 j 个数,dp[i][j] = dp[i-1][j] * (j+1) + dp[i-1][j-1] * (i-j)。这是状态转移方程。

为什么是这样呢,dp[i-1][j] * (j+1) 意思是,你前i-1个已经凑够 j 个了,那么我把 i 可以去替换这个 j 个任何一个,再加上,把这个 i 放在最后,

一共是 j+1个,所以乘以它。

 dp[i-1][j-1] * (i-j) 意思是已经够 j-1了,还差一个,然后那一个必须是 i ,所以用 i 去替换 i-j 个数,所以就是这个结果。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <stack>
using namespace std;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1000 + 5;
const int mod = 1e9 + 7;
const char *mark = "+-*";
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
int n, m;
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
inline int Min(int a, int b){  return a < b ? a : b; }
inline int Max(int a, int b){  return a > b ? a : b; }
LL dp[maxn][maxn];

void init(){
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i <= 1000; ++i)  dp[i][0] = 1;

    for(int i = 1; i <= 1000; ++i)
        for(int j = 0; j <= i; ++j)
            dp[i][j] = (dp[i-1][j] * (j+1) + dp[i-1][j-1] * (i-j)) % mod;
}

int main(){
    init();
    while(scanf("%d %d", &n, &m) == 2)   printf("%I64d\n", dp[n][m]);
    return 0;
}

  

HDU 3664 Permutation Counting (DP)

标签:

原文地址:http://www.cnblogs.com/dwtfukgv/p/5777852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!