uva11481 Arrange the Numbers(错位排列)
2015-05-07 19:00
441 查看
关键词:错位排列
题意:求1-n的条件排列个数
条件为:前m个数中有恰k个数满足a[i]==i
解法:递推。
1.前m个数中有k个数满足a[i]==i,删除这k个数,题意转化为前n-k个数种前m-k个数满足a[i]!=i的排列个数。
结论:1-n的排列中前m个数错位排列的个数
dp[i][j]:1-i的排列中前j个数错位排列的个数
1.第j个数排列在(j,i]序列中:可以看做第j个数与除去第j位的前i-1位元素错位排列后,第j个元素与(j,i]序列位置中的元素交换位置:dp[i-1][j-1]*(i-j)
2.第j个数排列在[1,j)序列中:可以看做在[1,j)位置中选择一个位置k给j填。仍然去除第j个位置,但是选择的k位置可以错排,也可以不用错排,因此dp值应转化为:dp[i-1][j-2]*(j-1)
综上:dp[i][j]=dp[i−1][j−1]∗(i−j)+dp[i−1][j−2]∗(j−1)
拓展
1:n个数的错位排列个数Dn=(Dn−1+Dn−2)∗(n−1)
证明:在1-n-1中选取一位,这一位既可以参与错排,也可以不参与错排(Dn−1+Dn−2);然后n放在第这一位,这一位上的数字放到第n位,因此,公式成立
错位排列的表达式Dn=[(n!/e)+0.5],即最接近(n!/e)的整数!
注:两个递推的原理相同,只不过一个是一维表达式,另一个是二维表达式
题意:求1-n的条件排列个数
条件为:前m个数中有恰k个数满足a[i]==i
解法:递推。
1.前m个数中有k个数满足a[i]==i,删除这k个数,题意转化为前n-k个数种前m-k个数满足a[i]!=i的排列个数。
结论:1-n的排列中前m个数错位排列的个数
dp[i][j]:1-i的排列中前j个数错位排列的个数
1.第j个数排列在(j,i]序列中:可以看做第j个数与除去第j位的前i-1位元素错位排列后,第j个元素与(j,i]序列位置中的元素交换位置:dp[i-1][j-1]*(i-j)
2.第j个数排列在[1,j)序列中:可以看做在[1,j)位置中选择一个位置k给j填。仍然去除第j个位置,但是选择的k位置可以错排,也可以不用错排,因此dp值应转化为:dp[i-1][j-2]*(j-1)
综上:dp[i][j]=dp[i−1][j−1]∗(i−j)+dp[i−1][j−2]∗(j−1)
拓展
1:n个数的错位排列个数Dn=(Dn−1+Dn−2)∗(n−1)
证明:在1-n-1中选取一位,这一位既可以参与错排,也可以不参与错排(Dn−1+Dn−2);然后n放在第这一位,这一位上的数字放到第n位,因此,公式成立
错位排列的表达式Dn=[(n!/e)+0.5],即最接近(n!/e)的整数!
注:两个递推的原理相同,只不过一个是一维表达式,另一个是二维表达式
#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 = 1000000007; using namespace std ; const ll maxn = 1000+10; ll t,n,m,k; ll dp[maxn][maxn]; ll c[maxn][maxn]; ll C(ll a,ll b){ if(a==b||b==0||a==0) return c[a][b]=1; if(c[a][b]!=-1) return c[a][b]; else return c[a][b]=(C(a-1,b)+C(a-1,b-1))%mod; } void init(){ memset(c,-1,sizeof(c)); memset(dp,0,sizeof(dp)); dp[0][0]=1; for(ll i=1;i<maxn-5;i++){ dp[i][0]=(dp[i-1][0]*i)%mod; for(ll j=1;j<=i;j++){ dp[i][j]=(dp[i-1][j-1]*(i-j))%mod; if(j>=2) dp[i][j]=(dp[i][j]+(dp[i-1][j-2]*(j-1))%mod)%mod; } } } int main(){ init(); scanf("%lld",&t); for(ll cas=1;cas<=t;cas++){ scanf("%lld%lld%lld",&n,&m,&k); printf("Case %lld: %lld\n",cas,(C(m,k)*dp[n-k][m-k])%mod); } return 0; }
相关文章推荐
- UVA - 11481 Arrange the Numbers
- uva 11481 Arrange the Numbers
- uva11481 - Arrange the Numbers N个数前M个错排
- UVA 11481 Arrange the Numbers (容斥)
- UVa:11481 Arrange the Numbers
- uva 11481 - Arrange the Numbers(计数问题)
- UVa 11481 Arrange the Number(容斥原理)
- LightOJ 1095 Arrange the Numbers-容斥
- LightOJ 1095 Arrange the Numbers(容斥原理)
- UVa 913 - Joana and the Odd Numbers
- UVa 11481 (计数) Arrange the Numbers
- lightoj 1095 - Arrange the Numbers 组合数学
- Light oj 1095 - Arrange the Numbers(错排)
- UVA913 Joana and the Odd Numbers【数学】
- LightOJ-1095 Arrange the Numbers
- Light OJ 1095 Arrange the Numbers(计数)
- Light OJ 1095 Arrange the Numbers (容斥)
- lightoj 1095 - Arrange the Numbers (错排数)
- uva 11471 Arrange the Tiles (DP)
- UVa 10712 - Count the Numbers