original link - https://nanti.jisuanke.com/t/41412
题意:
对于 n > 1 n>1 n>1,求出 ∏ i = 1 n a i = ∑ i = 1 n \prod_{i=1}^n a_i=\sum_{i=1}^n ∏i=1nai=∑i=1n的 n n n长度数组个数。
解析:
如果先不选择1,考虑选中了其他 x x x个数,设乘积为 m u l mul mul,和为 s u m sum sum,那么有添加 m u l − s u m mul-sum mul−sum个1后使得 ∏ i = 1 n a i = ∑ i = 1 n \prod_{i=1}^n a_i=\sum_{i=1}^n ∏i=1nai=∑i=1n。
那么考虑搜索的做法,当 m u l − s u m mul-sum mul−sum已经大于可以使用的1的数量时剪枝。
可以发现数量不会很大,因为 2 12 > 3000 2^{12}>3000 212>3000。
代码:
/*
* Author : Jk_Chen
* Date : 2019-09-15-12.22.19
*/
#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<
const LL mod=1e9+7;
const int maxn=6000+9;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
/*_________________________________________________________begin*/
LL fac[maxn];
LL ifac[maxn];
LL C(int i,int j){return fac[i]*ifac[j]%mod*ifac[i-j]%mod; }
LL Pow(LL a,LL b,LL mod){
LL res=1;
while(b>0){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
/*_________________________________________________________Pow*/
bool have[maxn];
LL ans[maxn];
int Q[20];
LL deal(int n,int one){
if(n==0)return 1;
unordered_map<int,int>vis;
rep(i,1,n){
vis[Q[i]]++;
}
LL ans=fac[n+one]*ifac[one]%mod;
for(auto P:vis){
ans=ans*ifac[P.second]%mod;
}
return ans;
}
void dfs(int num=0,int sum=0,int mul=1){
if(have[(mul-sum)+num])
ans[(mul-sum)+num]=(ans[(mul-sum)+num]+deal(num,mul-sum))%mod;
rep(i,max(2,Q[num]),6000){
if(mul*i-(sum+i)>3000-num-1)break;
Q[num+1]=i;
dfs(num+1,sum+i,mul*i);
}
}
int q[maxn];
int main(){
fac[0]=1;
rep(i,1,maxn-1)fac[i]=fac[i-1]*i%mod;
ifac[maxn-1]=Pow(fac[maxn-1],mod-2,mod);
per(i,maxn-2,0){
ifac[i]=ifac[i+1]*(i+1)%mod;
}
int t=rd();
rep(i,1,t){
q[i]=rd();
have[q[i]]=1;
}
dfs();
rep(i,1,t){
printf("%lld\n",ans[q[i]]);
}
return 0;
}