题目链接:点击查看
题目大意:对于n>1,求的长度为n的数组个数
题目分析:因为长度为n的数组中,组成数字相同但排列组合不同的数组,不算同一种情况,所以我们在求出一种满足条件的数组后,需要考虑所有排列组合的情况,然后枚举的时候也有技巧,如果盲目枚举3000位,那得枚举到何年何月。。我们需要分析一下这个式子,可以得出一个简单地结论,就是当n很大的时候,绝大部分都是1,为什么这么说呢,现在假设n>14,并且假设现在有14个大于1的数,然后其余的数都为1,因为2的14次方就已经大于3000了,所以那14个大于1的数累乘起来必定是大于3000的,所以将这些元素累加起来的结果是绝对不可能满足上述公式的。
现在已经剪枝了绝大部分,因为大于1的元素最多有13个,所以当n小于13的时候枚举n就行,当n大于13的时候,枚举一下13个不同的元素,然后剩下的用1补齐,然后计算全排列即可,因为我数论贼菜,所以全排列公式是我现学现卖的。。举个很简单的例子,比如3000个数中,有5个2,3个4,其余的都是1,那么排列组合就是(3000!)/(2992!*5!*3!),因为涉及到了除法,所以我们可以预处理一下每个全排列的逆元即可。
首先先说一下几个小性质,也是挺简单地性质,虽然我不会证明。。
- 每个枚举的都是小于等于n的
- 所有之和小于等于2*n
在dfs中还需要剪枝的地方就是乘积了,因为在枚举的时候,我选择枚举是不严格升序枚举的,所以当累乘大于2*n时就可以直接返回了,并且枚举每一位的时候,下限是上一次枚举的数值,上限是2*n/mul (mul为累乘到当前的值),因为要保证累乘的结果总是小于2*n,所以这样枚举也可以达到大幅降低时间复杂度的效果,下面挂上打表代码,因为跑了不到半分钟,然后如果是直接跑的话大概时间是3秒钟,但是题目给的是1秒钟,只能把3000个数值跑出来然后打表了。。
打表代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include