HYSBZ 4563 放棋子

题意:
给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。
题解:⑥
①这道题我们可以分析为错排问题:
一共 1~n n个数,对于任意数x都不在第x个位置上有多少方案数。
②为什么这么说呢(⊙o⊙)?
⑴我们可以注意到:每一行每一列有且只有一个障碍
⑵那么每一行障碍的位置对于答案没有任何实际影响
⑶如果我们按照每一行障碍的位置对行进行排序的话
⑷就转化成了第i行的棋子不能出现在第i个位置的问题
⑸也就是我们上面说的错排问题了
③那么错排问题的公式是什么呢?
f[i]=f[i-1]*(i-1)+f[i-2]*(i-1)
④原理:
⑴第一步,把第i个元素放在一个位置,比如位置k,一共有i-1种方法
⑵第二步,放编号为k的元素,这时有两种情况:
⒈把它放到位置i,那么,对于剩下的i-1个元素,由于第k个元素放到了位置i,剩下i-2个元素就有f[i-2]种方法
⒉第k个元素不把它放到位置i,这时,对于这i-1个元素,有f[i-1]种方法

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <string.h>
using namespace std;
struct BigInteger{
    int s[1005],len;
    BigInteger(){
        len=0;
        memset(s,0,sizeof(s));
    }
    BigInteger(const char *A){*this=A;}
    BigInteger(const int &A){*this=A;}
    void operator=(const char *A){
        len=strlen(A);
        for(int i=0;i<len;i++)
            s[i]=A[len-i-1]-'0';
    }
    void operator=(const int &A){
        char tmp[1005];
        memset(tmp,0,sizeof(tmp));
        sprintf(tmp,"%d",A);
        *this=tmp;
    }
    void clear(){
        while(len>1 && !s[len-1])len--;
    }
    BigInteger operator+(const BigInteger &A){
        BigInteger ans;
        ans.len=max(len,A.len)+1;
        int Carry=0;
        for(int i=0;i<len;i++){
            ans.s[i]=s[i]+A.s[i]+Carry;
            Carry=ans.s[i]/10;
            ans.s[i]%=10;
        }
        if(Carry)ans.s[len++]=Carry;
        ans.clear();
        return ans;
    }
    void operator+=(const BigInteger &A){
        *this=*this+A;
    }
    BigInteger operator-(const BigInteger &A){
        BigInteger ans;
        ans=*this;
        for(int i=0;i<len;i++){
            if(ans.s[i]<A.s[i])
                ans.s[i]+=10,ans.s[i+1]--;
            ans.s[i]=ans.s[i]-A.s[i];
        }
        ans.clear();
        return ans;
    }
    void operator-=(const BigInteger &A){
        *this=*this-A;
    }
    BigInteger operator-(const int &A){
        BigInteger tmp=A;
        return *this-tmp;
    }
    void operator-=(const int &A){
        *this=*this-A;
    }
    BigInteger operator*(const BigInteger &A){
        BigInteger ans;
        ans.len=len+A.len+1;
        int Carry=0;
        for(int i=0;i<len;i++){
            Carry=0;
            for(int j=0;j<A.len;j++){
                ans.s[i+j]+=s[i]*A.s[j]+Carry;
                Carry=ans.s[i+j]/10;
                ans.s[i+j]%=10;
            }
            ans.s[i+A.len]+=Carry;
        }
        ans.clear();
        return ans;
    }
    void operator*=(const BigInteger &A){
        *this=*this*A;
    }
    BigInteger operator*(const int &A){
        BigInteger tmp=A;
        return *this*tmp;
    }
    void operator*=(const int &A){
        *this=*this*A;
    }
    void Print(){
        for(int i=len-1;i>=0;i--)
            printf("%d",s[i]);
        printf("
");
    }
}f[205];
int main(){
    int n;scanf("%d",&n);
    f[0]=1;
    f[1]=0;
    for(int i=2;i<=n;i++)
        f[i]=(f[i-1]+f[i-2])*(i-1);
    f[n].Print();
    return 0;
}

 

原文地址:https://www.cnblogs.com/holy-unicorn/p/9510285.html