[BZOJ 4563][Haoi2016]放棋子(错排公式)

Posted Zars19

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 4563][Haoi2016]放棋子(错排公式)相关的知识,希望对你有一定的参考价值。

Description

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

Solution

其实和给出的障碍没什么关系,可以直接上错排公式(因为一开始的障碍可以看做一个排列,然后放棋子等同于要你生成一个新的不能有和原来位置相同元素的排列)

f[n]=(f[n-1]+f[n-2])*(n-1)(为什么的话上一篇里有说QwQ)

要加高精!

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n;
struct Bign
{
    static const int base=1000000;
    int len,s[1000];
    Bign(){len=1;memset(s,0,sizeof(s));}
    Bign(int num){*this=num;}
    Bign operator = (int num)
    {
        len=0;
        while(num)
        {
            s[len++]=num%base;
            num/=base;
        }
        return *this;
    }
    Bign operator + (const Bign& b)
    {
        Bign c;c.len=0;
        for(int i=0,g=0;g||i<max(len,b.len);i++)
        {
            g+=s[i]+b.s[i];
            c.s[c.len++]=g%base;
            g/=base;
        }
        return c;
    }
    Bign operator * (const int& b)
    {
        Bign c;c.len=0;
        for(int i=0;i<len||c.s[c.len];i++)
        {
            c.s[i]+=s[i]*b;
            c.s[i+1]+=c.s[i]/base;
            c.s[i]%=base;
            ++c.len;
        }
        return c;
    }
    void print()
    {
        printf("%d",s[len-1]);
        for(int i=len-2;i>=0;i--)
        printf("%06d",s[i]);
    }
}F[2];
int main()
{
    scanf("%d",&n);
    F[0]=1,F[1]=0;
    for(int i=2;i<=n;i++)
    {
        F[0]=(F[0]+F[1])*(i-1);
        swap(F[0],F[1]);
    }
    F[1].print();
    return 0;
}

 

以上是关于[BZOJ 4563][Haoi2016]放棋子(错排公式)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4563[Haoi2016]放棋子 错排+高精度

bzoj4563 [Haoi2016]放棋子

BZOJ4563 [Haoi2016]放棋子

[BZOJ 4563][Haoi2016]放棋子(错排公式)

[bzoj4563] [Haoi2016]放棋子

[BZOJ 4563]放棋子