诸侯安置

https://www.luogu.org/problemnew/show/P1240

行列不重复-->每一列放置的种类数跟前一列有关(递推)-->镜面和旋转的情况属于不同的方案-->按每列长度从小到大排-->得到第(2*i-1)和第(2*i)列长度相同,第(2*n-1)列长度最长且唯一,奇数列长度都为2*i-1,偶数与前一列相同-->第i列放了k个的情况=前i-1放了k个 + i-1放了k-1的情况*第i列可以放第k个的可能性,后者就是剩余的位置,即lon(i)-(k-1)-->得到表达式f[i][k]=f[i-1][k]+f[i-1][k-1]*(lon[i]-(k-1))

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #include<iostream>
 5 #include<stdlib.h>
 6 #include<algorithm>
 7 #define N 504
 8 using namespace std;
 9 int f[210][210],lon[210];
10 int main()
11 {
12     int n,t;
13     cin>>n>>t;
14     if(t>2*n-1){cout<<0<<endl;return 0;} //不存在的情况
15 
16     for(int i=1;i<n;i++) //记长度
17     lon[2*i-1]=lon[2*i]=2*i-1;
18     lon[2*n-1]=2*n-1;
19 
20     for(int i=0;i<=2*n-1;i++) f[i][0]=1; //初始化
21 
22     for(int i=1;i<=2*n-1;i++) //i为列数
23     for(int k=0;k<=lon[i];k++) //每一列至多放几k个的情况
24     {
25         f[i][k]=f[i-1][k]+f[i-1][k-1]*(lon[i]-(k-1));
26         f[i][k]%=N;
27     }
28    cout<<f[2*n-1][t]<<endl;
29    return 0;
30 }
View Code
原文地址:https://www.cnblogs.com/XXrll/p/10279235.html