首页 > 代码库 > NOIp模拟1 Permutation
NOIp模拟1 Permutation
试题描述 |
将 1 到 N 任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。 |
输入格式 |
N,K |
输出格式 |
答案 |
输入示例 |
5 2 |
输出示例 |
66 |
注释说明 |
20%数据:N <= 10 |
【分析】
dp[i][j]表示在前i个数中插入j个‘<’的方案数。
由于按顺序插入,所以每次插入的数都是当前序列中最大的,首先考虑在被‘<‘连接的两个数之间插入,这时‘<‘的数目不会改变,注意在序列的最左边插入也是一样的效果,所以我们得到了dp方程的第一项dp[i-1][j]*(j+1)。
再考虑在被‘>‘连接的两个数间插入,这时‘<‘数目会增加一,当i个数中有j个‘<‘时,‘>‘的数目为i-1-j,但与上面那种情况同理,在序列的最左端插入也会多一个‘<‘,所以我们得到了dp方程的第二项dp[i-1][j-1]*(i-j)。
最后得到的方程为dp[i][j]=dp[i-1][j]*(j+1)+dp[i-1][j-1]*(i-j)。
初始化条件为dp[i][0]=1(1<=i<=n),即当前序列为严格下降序列。
下面是50分程序,还没写高精度,高精度的实现方法后续会另写一篇文章总结。
【代码】
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 long long dp[105][105]; 5 int n, k; 6 7 int main() { 8 cin >> n >> k; 9 for (int i=1;i<=n;++i) dp[i][0]=1; 10 for (int i=1;i<=n;++i) 11 for (int j=1;j<=min(k, i-1);++j) 12 dp[i][j]=dp[i-1][j]*(j+1)+dp[i-1][j-1]*(i-j); 13 cout << dp[n][k] << endl; 14 }
【代码】
NOIp模拟1 Permutation
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。