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 }