标签:排列 color div 排列组合 com -- ++ pos ret
题目:https://nanti.jisuanke.com/t/41412
思路:dfs
先取ai>2 2^12>3000 因此至多取11个 其余用1补
(3000*2)-(3000+2)=2998 那么需要加入2998个1 正好3000位 所以 3000是ai最大取值
计算ans时 有重复元素的排列组合 :如1112233 res=7!/(3!*2!*2!)
另外预处理阶乘及其逆元
#include<bits/stdc++.h> #define ll long long using namespace std; const int mod=1e9+7; ll fac[3001];//阶乘 ll infac[3001];//逆元 ll ans[3001]; ll a[3001];//数列 int v[3001];// i在数组中的个数 ll qPow(ll n,int a) { ll res=1; while(a) { if(a&1) res=res*n%mod; n=n*n%mod; a>>=1; } return res; } void calc(int cur,int cnt) { for(int i=1;i<=cur;i++) v[a[i]]++; int res=fac[cnt]; for(int i=1;i<=3000;i++) if(v[i]>1) res=res*infac[v[i]]%mod; ans[cnt]=(ans[cnt]+res)%mod; } void dfs(int cur,int start,int idx,ll mul,ll sum,ll cnt) { if(cur==0) { memset(v,0,sizeof v); v[1]=mul-sum; calc(cnt,mul-sum+cnt); return; } for(int i=start;i<=3000;i++) { if(mul*i-sum-i>3000-cnt) return; a[idx]=i; dfs(cur-1,i,idx+1,mul*i,sum+i,cnt); } } int main() { memset(ans,0,sizeof ans); fac[0]=infac[0]=1; for(ll i=1;i<=3000;i++) fac[i]=fac[i-1]*i%mod,infac[i]=infac[i-1]*qPow(i,mod-2)%mod; for(int i=2;i<=11;i++) dfs(i,2,1,1,0,i); int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); printf("%d\n",ans[n]); } return 0; }
The Preliminary Contest for ICPC Asia Shanghai 2019 D. Counting Sequences I
标签:排列 color div 排列组合 com -- ++ pos ret
原文地址:https://www.cnblogs.com/c4Lnn/p/12090704.html