https://www.nowcoder.com/pat/2/problem/279 1023 考新郎
知识点:高中知识中的 排列和组合
&&:
1.排列的定义及其计算公式:
从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示。
A(n,m)=n(n-1)(n-2)……(n-m+1)= n!/(n-m)! 此外规定0!=1
2.组合的定义及其计算公式:
从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。
C(n,m)=A(n,m)∧2/m!=A(n,m)/m!; C(n,m)=C(n,n-m)。(其中n≥m)
思路:
根据错选的人数判断,运用相关数学知识。(重在两个函数)
**: 排列和组合的结果超出int的范围,需要long long。
&&:
1.组合的函数C(n,m)
long C(int n,int m) { int i; long long a=1; long long b=1; for(i = n; i >= 1; i--) { if(i >= n - m + 1) a *= i; if(i <= m) b *= i; } long long c = a / b; return c; }
2.排列的函数A(n,m)
long long A(int n, int m) { if(m == 1) return n; if(m == n) return 1; return n * A(n - 1, m); }
3.排列全错推理
1 2 3 4 5 6 ......
0 1 2 9 44 265 ......
long long fun(int n) { if(n == 1) return 0; if(n == 2) return 1; return (n - 1) * ( fun(n - 1) + fun(n - 2)); }
牛客AC代码:
#include <cstdio> #include <cstdlib> int C(int n,int m); long long fun(int); int main() { int n,m; while(scanf("%d %d",&n,&m) != EOF) { printf("%lld\n", C(n , n-m) * fun(m)); } return 0; } int C(int n,int m) { int i; long long a=1; long long b=1; for(i = n; i >= 1; i--) { if(i >= n - m + 1) a *= i; if(i <= m) b *= i; } long long c = a / b; return c; } long long fun(int n) { if(n == 1) return 0; if(n == 2) return 1; return (n - 1) * ( fun(n - 1) + fun(n - 2)); }