洛谷 P3182 [HAOI2016]放棋子(高精度,错排问题)
传送门
解题思路
不会错排问题的请移步——错排问题 && 洛谷 P1595 信封问题
这一道题其实就是求对于每一行的每一个棋子都放在没有障碍的地方的方案数。
因为障碍是每行、每列只有一个,所以答案不受障碍的影响。
这里障碍就等于是信封,棋子就等于是信,也是求所有的信都放错信封的方案数。
显然是错排问题。
公式:d(i)=(i-1)*(d(i-1)+d(i-2))。看一看数据范围,没有取余,所以需要用高精度。
注意
- 公式中是(i-1)而不是(n-1)——整整一个小时
- 高精度加法乘法混合运算中,这里是先乘后加。——整整半个小时
- c++函数中数组的引用可以用*数组名或者(&数组名)[数组大小]两种方法——十分钟
所以这样一道垃圾的题用了我接近两个小时。。。
AC代码
1 #include<iostream> 2 using namespace std; 3 const int maxn=1005; 4 int a[205][maxn]; 5 int n; 6 void add(int k){ 7 for(int i=1;i<=1000;i++){ 8 int x=a[k][i]; 9 a[k][i]=a[k-1][i]+a[k-2][i]; 10 a[k][i]*=k-1; 11 a[k][i]+=x; 12 a[k][i+1]+=a[k][i]/10; 13 a[k][i]%=10; 14 } 15 } 16 int main() 17 { 18 cin>>n; 19 a[2][1]=1; 20 for(int i=3;i<=n;i++){ 21 add(i); 22 } 23 int i=maxn; 24 while(--i&&a[n][i]==0&&i>1); 25 for(;i>0;i--) cout<<a[n][i]; 26 return 0; 27 }