题目描述

给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。

输入输出格式

输入格式:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

 

第一行一个N,接下来一个N*N的矩阵。N<=200,0表示没有障碍,1表示有障碍,输入格式参考样例

 

输出格式:

 

一个整数,即合法的方案数。

 

输入输出样例

输入样例#1:  复制
2
0 1
1 0
输出样例#1:  复制
1




错排问题
错排的种数
公式:D(n)=(n1)(D(n2)+D(n1))
特殊地,D(1) = 0, D(2) = 1D(1)=0,D(2)=1.

我们可以观察发现,每一行的障碍位置对答案并没有影响。

于是我们可以将此时的矩阵化成如下形式:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

此时障碍列的排列为: 1 2 3 4 于是我们问题可以转化为: 从每行中选出一个1~n1 n的没出现的书且和障碍不相同

即:问一个1~n1 n的数列的排列与原数列的位置都不相同的个数

所以这就是一个错位排序了,但是为了让代码量变大,便没有模数,所以要打高进度

 

 

P3182 [HAOI2016]放棋子 错排问题 随笔 第1张
#include<cstdio>
using namespace std;
// D(n)=(n-1)*(D(n-1)+D(n-2))
// D(1)=0 D(2)=1

int n;
int D[205][100005];

void ad(int now){
    int x=0;
    for(int i=1;i<100005;i++){
        D[now][i]=D[now-1][i]+D[now-2][i]+x;
        x=D[now][i]/10;
        D[now][i]%=10;
    }
    x=0;
    for(int i=1;i<100005;i++){
        D[now][i]=D[now][i]*(now-1)+x;
        x=D[now][i]/10;
        D[now][i]%=10;
    }
}

signed main(){
    scanf("%d",&n);
    D[2][1]=1;
    if(n==1||n==2){
        printf("%d",n-1);
        return 0;
    }
    for(int i=3;i<=n;i++)
        ad(i);
    int lenc=100004;
    while(D[n][lenc]==0) lenc--;
    while(lenc) printf("%d",D[n][lenc--]);
    return 0;
} 
View Code

 











扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄