题意:求元素为n个的子序列的个数满足.
思路:因为n<=3000,可以分析出最多有11个非1元素,dfs枚举剪枝,当所有非1元素的乘积 f 和加和 s 满足f-s+cnt>3000时,递归结束。一个序列的贡献为,(a, b, c为每种数的个数)
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e5+5;
const LL mod = 1e9+7;
LL quick_pow(LL a, LL b){
LL sum = 1;
while(b){
if(b&1) sum = sum*a % mod;
a = a*a%mod; b >>= 1;
}return sum;
}
LL fac[maxn], ifac[maxn];
int num[maxn];
LL compt(int n, int one){
unordered_map<int, int>mp;
for(int i=1; i<=n; i++) mp[num[i]] ++;
LL ans = fac[n+one] * ifac[one]%mod;
for(auto it : mp) ans = ans * ifac[it.second] % mod;
return ans;
}
LL ans[maxn];
void dfs(int cnt=0, int f=1, int sum=0){
ans[f-sum+cnt] = (ans[f-sum+cnt] + compt(cnt, f-sum))%mod;
for(int i=max(2, num[cnt]); i<=3000; i++){
if(f*i-(sum+i) > 3000-(cnt+1)) break;
num[cnt+1] = i;
dfs(cnt+1, f*i, sum+i);
}
}
int main()
{
//freopen("D:\\out.txt", "w", stdout);
fac[1]=ifac[1]=1; for(int i=2; i<=3005; i++) fac[i] = fac[i-1]*i%mod, ifac[i] = quick_pow(fac[i], mod-2);
dfs();
int t, n;
cin >> t;
while(t--){
cin >> n;
cout << (n==2?1:ans[n]) << endl;
}
}