zoukankan      html  css  js  c++  java
  • [HAOI2016] 放棋子及错排问题

    题目

    Description

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

    Input

    第一行一个N,接下来一个N*N的矩阵。N<=200,0表示没有障碍,1表示有障碍,

    Output

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

    Solution

    我们先来科普一下错排问题。

    错排问题指考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。 n个元素的错排数记为D(n)。 研究一个排列错排个数的问题,叫做错排问题或称为更列问题。  ---《百度百科》

    看上去这就是一个递推问题,那么递推式是如何推出来呢?

    当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
    第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
    第二步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
    综上得到
       D(n) = (n-1) *(D(n-2) + D(n-1))
    特殊地,D(1) = 0, D(2) = 1.
     
    知道了这个之后,这题就是一个裸的高精了。
    Code
    // By YoungNeal
    #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;
    } 
    当你走进这欢乐场
  • 相关阅读:
    Asp.net把UTF-8编码转换为GB2312编码
    润乾报表中文传参乱码的问题
    润乾报表中填报中文出现乱码
    SQL Developer不能删除和复制及部分键失效问题
    .NET类型转换的常用方式
    .net中三种数据类型转换区别((int),Int32.Parse() 和 Convert.toInt32() )
    什么是SFP光模块?
    什么是"双活"
    存储软件特性
    【分享】给自己的博客园添加一个板娘(可选)
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/8485399.html
Copyright © 2011-2022 走看看