uva 1485 Permutation Counting(递推)

关键词:递推、交换法!!!、更新递推式
题意:求满足条件的1-n排列a[1,2…n]个数
条件:恰有k个数,满足a[i]>i
解法:递推
dp[i][j]:前i个数中恰有j个数满足a[k]>k的排列个数。
法一:
用dp[i][j]更新后面的dp值。
1第i+1个数与a[k]>k的位置上的数交换/第i+1个数位于第i+1个位置,dp值均变为dp[i+1][j] ,已知dp[i][j]个排列中恰有j个数满足a[k]>k。因此dp[i+1][j]=(j+1)*dp[i][j]
2.第i+1个数与a[k]>=k的位置上的数交换,dp值变为dp[i+1][j+1],dp[i+1][j+1]=dp[i][j]*(i-j)

法二:直接dp
方法与上述类似,考虑前i-1个元素已经排列好,将第i个元素与前面的某些元素交换
dp[i][j]=dp[i-1][j](j+1)+dp[i-1][j-1](i-j)

#include <stdio.h>
#include <string.h>
#include <set>
#include <map>
#include <algorithm>
#include<vector>
#include<complex>
#include<iostream>
#define pi acos(-1)
#define X first
#define Y second
#define ll long long
#define MP(x,y) make_pair((x),(y))
#define INF 0x3f3f3f3f
const ll mod = 1e9+7;
using namespace std ;
const ll maxn = 1000+10;

ll n,k;
ll dp[maxn][maxn];//dp[i][j]:前i个数字组成的序列中有j个满足条件的排列个数

int main(){
        memset(dp,0,sizeof(dp));
        dp[1][0]=1;
        for(ll i=1;i<maxn-5;i++){
            for(ll j=0;j<=i;j++){
                dp[i+1][j]=(dp[i+1][j]+(dp[i][j]*(j+1))%mod)%mod;
                dp[i+1][j+1]=(dp[i+1][j+1]+(dp[i][j]*(i-j))%mod)%mod;
            }
        }
    while(scanf("%lld%lld",&n,&k)!=EOF){
        printf("%lld\n",dp[n][k]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值