2019 ICPC Nanjing Regional I. Space Station (DP && Hash)

Title:

Have nnn numbersa 1, 2,.. n a_{1,2,..n}a1,2,..n, Your initial energy is a 0 a_0a0, Each time you can only select the number less than or equal to the current energy, after selecting the number ai a_iaiAfter the current energy will add ai a_iai, Find the number of plans after selecting all numbers mod 1 e 9 + 7 mod\ 1e9+7m o d 1 e 9 +7
n ≤ 1 e 5, 0 ≤ ai ≤ 50 n \ le1e5,0 \ le a_i \ le 50n1e5,0ai50

Problem-solving ideas:

Notice ai a_iaiVery small, the current energy exceeds ai a_iaiAfter the upper limit, you can choose at will. So we can consider direct memory search, pay attention to picking out 0 alone.
The number of search nodes = the number of divisions of 50 = 204226 The number of search nodes = the number of divisions of 50 = 204226Search Cable junction point number mesh=. 5 0 The classified fraction number=2 0 4 2 2 6 .
The current search state can be hashed and stored in unorder_map, or you can write a hash to store it yourself. The direct map structure will time out, and the map hash value will also time out.
ComplexityO (f (50) ∗ 50 ∗ Average search time of mapping function) O(f(50)*50* Average search time of mapping function)O(f(50)50Mapping radio function number level average search to find the time between )
AC codes:

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define ull unsigned long long
using namespace std;
const int mod = 1e9 + 7;
struct node{
    
    
    int a[51];
    node(){
    
    memset(a,0,sizeof a);}
};
const int maxn = 1e5 + 50;
int fac[maxn], ifac[maxn];
int qm(int a, int b){
    
    
    int res = 1;
    while(b){
    
    
        if(b&1) res = (ll)res*a%mod;
        a = (ll)a*a%mod;
        b >>= 1;
    }return res;
}
int n;
unordered_map<ull,int> mp;
ull sed = 131;
ull p[55];
node state;
int dp(int cur, int res){
    
    
    if(res == 0) return 1;
    if(cur >= 50){
    
    
        return fac[res];
    }
    ull ha = 0;
    for(int i = 50; i > 0; --i) ha = ha*sed+state.a[i];
    if(mp.find(ha) != mp.end()) return mp[ha];
    int ans = 0;
    for(int i = 1; i <= cur; ++i){
    
    
        if(!state.a[i]) continue;
        int t = state.a[i];
        --state.a[i];
        ans = (ans+(ll)t*dp(cur+i, res-1)%mod)%mod;
        ++state.a[i];
    }
    mp[ha] = ans;
    return ans;
}
int main()
{
    
    
    p[0] = 1; for(int i = 1; i < 55; ++i) p[i] = p[i-1]*sed;
    fac[0] = ifac[0] = 1;
    for(int i = 1; i < maxn; ++i) fac[i] = (ll)fac[i-1]*i%mod;
    ifac[maxn-1] = qm(fac[maxn-1], mod-2);
    for(int i = maxn-2; i > 0; --i) ifac[i] = (ll)ifac[i+1]*(i+1)%mod;
    scanf("%d", &n);
    int cur, num = 0, z = 0; scanf("%d", &cur);
    for(int i = 1; i <= n; ++i){
    
    
        int x; scanf("%d", &x);
        if(x == 0) z++;
        else state.a[x]++, num++;
    }
    int ans = dp(cur, num);
    ans = (ll)ans * (ll)fac[n]%mod*(ll)ifac[n-z]%mod;
    cout<<ans<<endl;
}

Guess you like

Origin blog.csdn.net/qq_43202683/article/details/104099322