Counting Sequences I(搜索 数学)

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 mulsum个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 mulsum已经大于可以使用的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;
}

你可能感兴趣的:(图论/搜索,数论/数学,例题)