#错排,高精度#洛谷 3182 [HAOI2016]放棋子

题目


分析

这题目太迷惑人了:

每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列

\(n\) 个棋子也满足每行只有一枚棋子,每列只有一枚棋子

仔细想想会发现求的是错排方案,那也就是\(D(n)=(n-1)(D(n-1)+D(n-2))\)

题目要求高精度


代码

#include <cstdio>
#include <cstring>
#define rr register
using namespace std;
typedef long long lll;
const lll mod=1000000000;
struct Big{
    lll p[61]; int len;
    inline Big operator +(const Big &t)const{
	    rr lll g=0,s=0; rr Big c;
		c.len=len>t.len?len:t.len,
		memset(c.p,0,sizeof(c.p));
	    for (rr int i=1;i<=c.len;++i)
	    	s=p[i]+t.p[i]+g,c.p[i]=s%mod,g=s/mod;
		if (g) c.p[++c.len]=g;
		return c;
	}
	inline void mul_int(int x){
		rr lll g=0,s=0;
		for (rr int i=1;i<=len;++i)
			s=p[i]*x+g,p[i]=s%mod,g=s/mod;
		while (g) p[++len]=g%mod,g/=mod;
	}
	inline void Print(){
		printf("%lld",p[len]);
		for (rr int i=len-1;i;--i)
		    printf("%09lld",p[i]);
	}
}dp[211];
signed main(){
	rr int n; scanf("%d",&n);
	if (n==1) return !printf("0");
	if (n==2) return !printf("1");
	dp[1].p[dp[1].len=1]=0,
	dp[2].p[dp[2].len=1]=1;
	for (rr int i=3;i<=n;++i)
		dp[i]=dp[i-1]+dp[i-2],
		    dp[i].mul_int(i-1);
	dp[n].Print();
	return 0;
} 
posted @ 2020-12-09 17:45  lemondinosaur  阅读(51)  评论(0编辑  收藏  举报