D、E、F题:孙晨曦
题解:
D题题解:组合数。
(直接选出来C(n,k)个位置,然后这k个位置取全排列的话,需要考虑去重,所以换个选法)
这样做,先选出k个位置,然后只取让这k个位置都不能选择自己的indice的排列
例如,3个数,就只能选取231,312这两种排列。
经模拟得出1个数有0个这种排列,2个数有1个这种排列,3个数有2个,4个数有9个。
设个数组p[1]=0,p[2]=1,p[3]=2,p[4]=9
所以就可以得到,对于n,k,答案为
C(n,k)*p[k]+C(n,k-1)*p[k-1]+...+C(n,1)*p[1] +1
最后这个+1是因为以上过程没取从小到大顺序的这一种排列(1234567),所以要加上。。。思路挺简单,题解好像写的有点麻烦了
E题题解:折半搜索(meet in the middle)。
n=35,所以用折半搜索降低搜索的复杂度
用两个set存两次搜索的模m下的每个和
然后合并,更新最大值。
合并的方法是枚举第一个set的值(设为i),用upper_bound从第二个set中找第一个大于m-1-i的位置,有种情况:
①如果这个位置是set2.begin()的话,就说明set2中每个数加上i,都比m大,都要取余,那么set2中加i模m的值最大的数应该是set2中最后一个数,即取[set2.end()-1]的位置上的那个数。
②如果不是set2的首位置,那么set2中加i模m的最大值应该就是[这个位置-1]的位置上的那个数。
(下面是折半搜索的详解和两个例题)
https://blog.csdn.net/qq_45530271/article/details/104239624