为了使得方案的形式较为单一,不妨强制物品体积为1或$ge lceilfrac{w}{2} ceil$,那么假设最终有$x$个1且$ge lceilfrac{w}{2} ceil$的物品体积依次为$a_{1},a_{2},...,a_{n-x}$,不难发现方案数即为$sum_{i=1}^{n-x}{xchoose w-a_{i}}$
暴力枚举$x$,并不妨再强制方案数恰为$k$(而不是模$p$意义下),此时即选不超过$n-x$个${xchoose i}$使得其和恰为$k$(其中$iin [0,lfloorfrac{w}{2} floor]$,由于$wge 50$不妨变为$in [0,lfloorfrac{x}{2} floor]$,即问题与$w$无关)
每一次选$i=max_{0le jle 8,{16choose j}le k}j$,由于${xchoose 0}=1$,重复此过程最终总可得到$k$,并考虑所有$kin [0,2cdot 10^{4}]$后可以发现只需要取$x=13$或$14$即可保证有解
时间复杂度为$o(tn)$,可以通过
(dark_bzoj上该题似乎没有spj)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 15 4 vector<int>v; 5 int t,n,m,x,w,C[N][N]; 6 int main(){ 7 for(int i=0;i<N;i++){ 8 C[i][0]=C[i][i]=1; 9 for(int j=1;j<i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j]; 10 } 11 scanf("%d",&t); 12 while (t--){ 13 scanf("%d%*d%d",&w,&n); 14 for(int x=13;x<=14;x++){ 15 m=n; 16 v.clear(); 17 for(int i=0;i<x;i++)v.push_back(1); 18 for(int i=(x>>1);i>=0;i--){ 19 for(int j=0;j<m/C[x][i];j++)v.push_back(w-i); 20 m%=C[x][i]; 21 } 22 if (v.size()<=40){ 23 printf("%d ",(int)v.size()); 24 for(int i=0;i+1<v.size();i++)printf("%d ",v[i]); 25 printf("%d ",v.back()); 26 break; 27 } 28 } 29 } 30 return 0; 31 }