#错排,高精度#洛谷 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;
}