4563: [Haoi2016]放棋子

8 篇文章 0 订阅

4563: [Haoi2016]放棋子

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 257   Solved: 161
[ 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

HINT

Source

[ Submit][ Status][ Discuss]

确保每行有且只有一个障碍,每列有且只有一个障碍,
显然,交换两列的情况对答案并不影响
那么就把所有障碍交换成从左上到右下的一条对角线的形式
此时,第i行第i列一定不能放棋子
那么原问题就转换成求长度为n的错位排列的方案数,,显然要高精度
递推式,,fi = (fi-1 + fi-2)*(i-1)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

typedef long long LL;
const LL mo = 100000000;

struct data{
	LL len,a[111];
	data(){memset(a,0,sizeof(a)); len = 0;}
	data operator + (const data &b)
	{
		data c;
		int Len = max(len,b.len);
		for (int i = 0; i < Len; i++)
		{
			c.a[i] += a[i] + b.a[i];
			c.a[i+1] += c.a[i] / mo;
			c.a[i] %= mo;
		}
		c.len = c.a[Len]?Len+1:Len;
		return c;
	}
	data operator * (const LL &t)
	{
		data c;
		for (int i = 0; i < len; i++)
		{
			c.a[i] += a[i] * t;
			c.a[i+1] += c.a[i] / mo;
			c.a[i] %= mo;
		}
		c.len = c.a[len]?len+1:len;
		return c;
	}
}A,B;

void Print(int x,int y)
{
	if (y == 8)
	{
		printf("%d",x);
		return;
	}
	Print(x / 10,y + 1);
	printf("%d",x%10);
}

int n;

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> n;
	if (n == 1) {cout << 0; return 0;}
	A.len = 1; B.len = 1; B.a[0] = 1;
	for (int i = 3; i <= n; i++)
	{
		data C = (A + B)*(i-1);
		A = B; B = C;
	}
	cout << B.a[B.len - 1];
	for (int i = B.len - 2; i >= 0; i--) Print(B.a[i],1);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值