https://codeforces.com/problemset/problem/525/E

https://codeforces.com/problemset/problem/525/E
每个仙女有三种情况,枚举一下,n对半分,使得复杂度变成o(k*3^(n/2))
用map统计的时候,每次如果跑for的话会有很多重复的,这样可以直接存下来前缀和

for(auto i:mp){
        for(int j=1;j<=25;j++){
            mp[i.first][j]+=mp[i.first][j-1];
        }
    }

 


我第一次尝试用这种方式存前缀和,只能说auto太好用啦

 

#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<string>
#include<cmath>
#include<assert.h>
#include<queue>
#include<stack>
#include<stdlib.h>
#include<ctime>
#include<map>
#include<unordered_map>
typedef long long ll;
#define INF 0x3f3f3f3f
#define N 1000010
#define p(a) putchar(a)

using namespace std;
ll n,k,G,ans;
ll a[100],g[20];
map<ll,map<ll,ll>>mp;

inline void dfs(ll sum,ll cnt,ll pos){//总和,下凡次数,
    if(cnt>k || sum>G) return;
    if(pos==n/2+1){
        mp[sum][cnt]++;
        return;
    }
    if(a[pos]<=18 && sum+g[a[pos]]<=G){
        dfs(sum+g[a[pos]],cnt+1,pos+1);
    }
    dfs(sum+a[pos],cnt,pos+1);
    dfs(sum,cnt,pos+1);
}

inline void dfs1(ll sum,ll cnt,ll pos){//总和,下凡次数,
    if(cnt>k || sum>G) return;
    if(pos==n+1){
        //for(int i=0;i<=k-cnt;i++) ans+=mp[G-sum][i];
        ans+=mp[G-sum][k-cnt];
        return;
    }
    if(a[pos]<=18 && sum+g[a[pos]]<=G){
        dfs1(sum+g[a[pos]],cnt+1,pos+1);
    }
    dfs1(sum+a[pos],cnt,pos+1);
    dfs1(sum,cnt,pos+1);
}

signed main(){
    cin>>n>>k>>G;
    for(ll i=1;i<=n;++i) cin>>a[i];
    g[0]=1;
    for(ll i=1;i<=18;++i) g[i]=g[i-1]*i;
    dfs(0,0,1);
    for(auto i:mp){
        for(int j=1;j<=25;j++){
            mp[i.first][j]+=mp[i.first][j-1];
        }
    }
    dfs1(0,0,n/2+1); 
    cout<<ans;
    return 0;
}

 

posted @ 2020-05-29 22:52  WeiAR  阅读(305)  评论(0编辑  收藏  举报