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; }