输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。
对应每一组数据,输出一个正整数,表示无人收到自己邮件的种数。
2<br/>3
1<br/>2
//递归思想,第n个收件人可以递归到n-1个收件人与n-2个收件人之和 #include<iostream> using namespace std; long int Failrec(int n) { if(n<2) return 0; if(n==2) return 1; if(n==3) return 2; return (n-1)*(Failrec(n-1)+Failrec(n-2)); } int main() { int n; while(cin>>n) { int count=0; cout<<Failrec(n)<<endl; } return 0; }
// 主要是练练语法,这种题目的思想总是很难想到。所谓的动态规划问题:假设a放进了B中:分两种情况, //一种情况是b放在A中,有D(n-2)种方法,另一种情况是b没有放在A中,实际上就是把b,c,d...放进 //A,C,D...中也就是有D(n-1)放法,而把a放进C,D,E...中有同样的D(n-1) + D(n-2)种放法,所以有n封信 //就应该有(n-1)[D(n-1) + D(n-2)]种放法。 lst = [0, 0, 1] for i in range(3,21): lst.append((i-1)*(lst[i-1]+lst[i-2])) while True: try: N = int(input()) print(lst[N]) except: break #include <stdio.h> #define maxN 21 int main() { int i; int N; long long a[maxN] = {0, 0, 1, 2}; for(i=4;i<maxN;i++) { a[i] = (i-1)*(a[i-1] + a[i-2]); } while(scanf("%d", &N)!=EOF) { printf("%lld\n", a[N]); } }
#include<stdio.h> int N=0; void dfs(int,int); int book[100]={0}; int main() { int n; scanf("%d",&n); dfs(0,n); printf("%d",N); } void dfs(int step,int n) { if(step==n) N++; else { int i; for(i=0;i<n;i++) if(book[i]==0&&i!=step) //没访问过并且自己的位置的编号不等于自己的值 { book[i]=1; dfs(step+1,n); book[i]=0; } } }//这是不需要什么数学公式推导的最暴力的方法
import java.util.Scanner;
//用的是单步最优的考虑想法,从最后一步开始考虑。
//为了方便理解,假设有5个人ABCDE,原来只有4个人ABCD。则多出来的一个人E,
//多出来的邮件E必定发错给ABCD中一个,共四种方法。假设给E的邮件发给了D,则
// 人 : A B C D E
// 邮件: E
//则发给D的邮件D有两种情况:一是正好发给了人E,二是发给了E以外的人(ABC)
//若情况一:变成了3人各自错收了邮件。
//若情况二:由于D不能发给E,我们可以假象D就是E(和原来等价),则此时变成了ABCE错发给ABCE,就等价于4人错收邮件。
//这样就很明白了,f(n)=(n-1)*[f(n-2)+f(n-1)]
public class Main {
public static void main(String[] args) {
Scanner in= new Scanner(System.in);
long c[]=new long[22];
c[2]=1;
c[3]=2;
for(int i=4;i<22;i++){
c[i]=(i-1)*(c[i-1]+c[i-2]);
}
while(in.hasNext()){
int n=in.nextInt();
System.out.println(c[n]);
}
}
}
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); long[] arr = new long[21]; arr[0] = 0; arr[1] = 0; arr[2] = 1; for(int i = 3;i < arr.length;i++){ arr[i] = (i - 1) * (arr[i - 1] + arr[i - 2]); } System.out.println(arr[n]); } } }
#include <iostream> #include <vector> using namespace std; int main() { int n; while(cin >> n) { vector<long long> v(n + 1, 0); v[1] = 0; v[2] = 1; for(int i = 3; i <= n; i++) v[i] = (i - 1) * (v[i - 1] + v[i - 2]); cout << v[n] << endl; } return 0; }
import java.util.*; public class Main { public static void main(String[] args){ Scanner scan = new Scanner(System.in); long[] a = new long[22]; a[2] = 1; a[3] = 2; for (int i = 4; i < 22; i++){ a[i] = (i-1)*(a[i-1]+a[i-2]); } while (scan.hasNext()){ int n = scan.nextInt(); System.out.println(a[n]); } } }
//详细解说看博客 import java.util.Scanner; public class Main2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); long sum = count(n); System.out.println(sum); } } //计算所有人都收不到自己的邮件的情况情况:错排算法 private static long count(int n) { if (n == 1) { return 0; } else if (n == 2) { return 1; } else { return (n - 1) * (count(n - 1) + count(n - 2)); } } } ———————————————— 版权声明:本文为CSDN博主「峰回路转」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_44840148/article/details/104723196
while True: try: n, num = int(input()), [1, 2] cout = 2 while len(num) < n: num.append((num[-1] + num[-2])*(cout+1)) cout += 1 print(num[-2]) except: break
#include <iostream> using namespace std; int main() { long long num[20] = {1, 2}; for (int i = 2; i < 20; i++) num[i] = (num[i-1] + num[i-2]) * (i + 1); int n; while (cin >> n) { cout << num[n-2] << endl; } return 0; }
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int main() { int n,i; long long a[25]={0,0,1}; for(i=3;i<=20;i++) { a[i] =(i-1)*(a[i-2]+a[i-1]); } while(cin>>n) { cout<<a[n]<<endl; } return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); System.out.println(count(n)); } } /** * 错排算法,注意是long型 * @param n * @return */ public static long count(int n) { if (n == 1) { return 0; } else if (n == 2) { return 1; } else { return (n - 1) * (count(n - 1) + count(n - 2)); } } }
有了递推公式,一切就迎刃而解了。
int main (void)
{
long long der[ 21 ] = { 0, 0, 1 };
int i;
for ( i = 3; i < 21; i++ ){
der[ i ] = ( i - 1 ) * ( der[ i - 2] + der[ i - 1 ] );
}
int n;
while ( scanf( "%d", &n ) != EOF ){
printf("%lld\n", der[ n ] );
}
return 0;
}