【u223】放牙刷

【题目链接】:

【题解】

错排公式
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\n",f[n]);
    return 0;
}
posted @ 2017-10-04 18:45  AWCXV  阅读(143)  评论(0编辑  收藏  举报