错位排列
递推公式
分析:
假设有信封A,B,C,D...;信件1,2,3,4...;全部装错有f(n)种情况。
这里分两种情况考虑:①前面n-1个信封全部装错;②前面n-1个信封有一个没有装错其余全部装错。
①前面n-1个信封全部装错:因为前面n-1个已经全部装错了,所以第n封只需要与前面任一一个位置交换即可,总共有f(n-1)*(n-1)种情况。
②前面n-1个信封有一个没有装错其余全部装错:为什么考虑这种情况,因为n-1个信封中如果有一个没装错,那么我们把那个没装错的与n交换,即可得到一个全错位排列情况。
得到这种情况的种数也很简单,即是忽略掉那个没装错的情况去排列其他的信封的全错排种数f(n-2)*(n-1)。
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排; 然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个. 最后,揭开盖头,如果找错了对象就要当众跪搓衣板...
看来做新郎也不是容易的事情...
假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.
Output
Sample Input
2 2 2 3 2Sample Output
1 3
错排:有n对新婚夫妇,对应新娘在(1-n)n个位置上,让各位新郎寻找自己的新娘,全部找错共有多少种找法,记n个元素的错排总数为f(n)假设有n个新郎,第一个新郎可找 2-n 的任一个位置,共n-1种找法
设第一个新郎找到了第 k 个位置,若此时第 k 个新郎正好找到了第 1 个位置,则只要将剩下的 n-2 错排,即f (n-2),就能实现全错排,若第k个新郎没有找到第1个位置,则将 n-1 个位置错排,即为f(n-1)
由递推可得,f(n)=(n-1)*(f(n-1)+f(n-2))
N个新郎找出M个新郎找错新娘,我们需要用到排列组合在 N 个新郎中选出是哪 M 个新娘,就是C(n,m)=n!/m!/(n-m)!
用该组合数再去乘错位排列数就是该结果
1 #include<cstdio> 2 #include<algorithm> 3 #define ll long long int 4 using namespace std; 5 ll f[30]; 6 ll c[30]; 7 int main() 8 { 9 ll n,m,t,i,ans; 10 f[1]=0; 11 f[2]=1; 12 for(i=3;i<=30;i++)///错排 13 { 14 f[i]=(i-1)*(f[i-1]+f[i-2]); 15 } 16 c[0]=1; 17 c[1]=1; 18 for(i=2;i<=30;i++)///求前i项阶乘之和 19 { 20 c[i]=c[i-1]*i; 21 } 22 scanf("%lld",&t); 23 while(t--) 24 { 25 scanf("%lld%lld",&n,&m); 26 ans=c[n]/(c[m]*c[n-m]); 27 printf("%lld\n",ans*f[m]); 28 } 29 }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
为了活跃气氛,组织者举行了一个别开生面、奖品丰厚的抽奖活动,这个活动的具体要求是这样的:
首先,所有参加晚会的人员都将一张写有自己名字的字条放入抽奖箱中;
然后,待所有字条加入完毕,每人从箱中取一个字条;
最后,如果取得的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
大家可以想象一下当时的气氛之热烈,毕竟中奖者的奖品是大家梦寐以求的Twins签名照呀!不过,正如所有试图设计的喜剧往往以悲剧结尾,这次抽奖活动最后竟然没有一个人中奖!
我的神、上帝以及老天爷呀,怎么会这样呢?
不过,先不要激动,现在问题来了,你能计算一下发生这种情况的概率吗?
不会算?难道你也想以悲剧结尾?!
1 #include<stdio.h> 2 #include <stdlib.h> 3 int main() 4 { 5 long long f[21]= {0};//定义不超过21的长整型数组用来存放错误的抽取 6 f[1]=0; 7 f[2]=1; 8 for(int i=3; i<21; i++) 9 f[i]=(i-1)*(f[i-1]+f[i-2]);//递推求值 10 int C; 11 scanf("%d",&C); 12 while(C--) 13 { 14 int n; 15 scanf("%d",&n); 16 long long sum=1; 17 for(int j=2; j<=n; j++) 18 sum*=j;//求阶乘,表示的是所有的抽取方法 19 double b=100.0*f[n]/sum; 20 printf("%.2f%%\n",b); 21 } 22 return 0; 23 }
本文作者:王陸
本文链接:https://www.cnblogs.com/wkfvawl/p/9373204.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步