bzoj4563: [Haoi2016]放棋子(错排+高精)

4563: [Haoi2016]放棋子

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 387  Solved: 247
[Submit][Status][Discuss]

Description

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

 

Input

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

 

Output

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

 

Sample Input

2
0 1
1 0

Sample Output

1
 
/*
每一行每一列只能放1个求方案数 转化为错排问题
练习高精压位 压9位。。。
*/
#include <iostream>
#include <cstdio>
#include<iomanip>

#define N 2001
#define mod 1000000000
#define _ 9
#define ll long long

using namespace std;
ll n;
struct num
{
    ll d[N],w;
/*    void print()
    {
        for (ll i=w;i>=1;i--) cout<<d[i];
        printf("\n");
    }*/
}D[N],id;

num operator +(num p1,num p2)
{
    num ret=id;
    ll g=0;
    if (p1.w<p2.w) swap(p1,p2);
    ret.w=p1.w;
    for (ll i=1;i<=p1.w;i++)
    {
        ret.d[i]=(p1.d[i]+p2.d[i]+g)%mod;
        g=(p1.d[i]+p2.d[i]+g)/mod;
    }
    while(g) ret.d[++ret.w]=g%mod , g/=mod;
    return ret;
}

num mul(num p1,ll p2)
{
    num ret=id;
    ret.w=p1.w;
    ll g=0;
    for (ll i=1;i<=p1.w;i++)
    {
        ret.d[i]=(p1.d[i]*p2+g)%mod;
        g=(p1.d[i]*p2+g)/mod;
    }
    while(g) ret.d[++ret.w]=g%mod,g/=mod;
    return ret;
}

ostream& operator << (ostream &os,num x)
{
    ll i;
    os<<x.d[x.w];
    for(i=x.w-1;i;i--)
        os<<setfill('0')<<setw(_)<<x.d[i];
    return os;
}

int main()
{
    scanf("%d",&n);
    if (n == 1)
    {
        puts("0");
        return 0;
    }
    D[1]=id;
    D[2].w=D[2].d[1]=1;
    for (ll i=3;i<=n;i++)
      D[i] = mul((D[i-1]+D[i-2]),i-1);
    cout<<D[n];
    return 0;
}

 

posted @ 2017-09-19 15:01  安月冷  阅读(144)  评论(0编辑  收藏  举报