The Preliminary Contest for ICPC Asia Shanghai 2019

D:Counting Sequences I

题意:求元素为n个的子序列的个数满足The Preliminary Contest for ICPC Asia Shanghai 2019.

思路:因为n<=3000,可以分析出最多有11个非1元素,dfs枚举剪枝,当所有非1元素的乘积 f 和加和 s 满足f-s+cnt>3000时,递归结束。一个序列的贡献为The Preliminary Contest for ICPC Asia Shanghai 2019,(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;
    }
}

 

上一篇:2020 ICPC Shanghai C - Sum of Log


下一篇:springboot2.0 连接数据库