【题目链接】:
【题解】
错排公式
f[n] = (n-1)*(f[n-1]+f[n-2]);
这样理解;
要从n-1和n-2递推到n;
假设第n个位置上的数要放在前n-1个位置中的k位置;则有n-1种选择;
则对于第k个位置上原本的元素;
有两种情况;
①
k那个元素到第n个位置上;
则剩下n-2个数字错排;即f(n-2);
②
k那个元素不到第n个位置上;
则我们先把刚才移到k号位置上的元素移回n位置;
然后前n-1个元素错排;->f(n-1);
这样在第k号位置上的元素就不可能是原来在k号位置上的元素了;
则我们在用第n号位置上的元素和新的第k号位置上的元素交换;
这样最开始那个在第k位置上的元素就不在第n号位置上了;
综上
得到递推式
f(n)=(n-1)*(f(n-1)+f(n-2));
//扩展一下通项公式D(n) = n! [(-1)^2/2! + … + (-1)^(n-1)/(n-1)! + (-1)^n/n!].
【完整代码】
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;
void rel(LL &r)
{
r = 0;
char t = getchar();
while (!isdigit(t) && t!='-') t = getchar();
LL sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
}
void rei(int &r)
{
r = 0;
char t = getchar();
while (!isdigit(t)&&t!='-') t = getchar();
int sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
}
const int MAXN = 1e5+100;
const int MOD = 1206;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
int n;
LL f[MAXN];
int main()
{
//freopen("F:\rush.txt","r",stdin);
f[0] = 0,f[1] = 0,f[2] = 1;
scanf("%d",&n);
rep1(i,3,n)
{
f[i] = (i-1)*(f[i-1]+f[i-2]);
f[i]%=MOD;
}
if (n<=1)
puts("No Solution!");
else
printf("%I64d
",f[n]);
return 0;
}