输入包含多组数据,每组数据包含一个正整数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;
}