题目地址:Anya and Cubes
比赛的时候居然没想起中途相遇法。。。这题也是属于想起来就很简单系列。
中途相遇法也叫折半搜索。就是处理前一半,把结果储存起来,再处理后一半,然后匹配前一半存储的结果。
代码如下:
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=200000+10;
map<LL,int>mp[30];
int a[30], m, k, n;
LL fac[30], ans, s;
void init()
{
int i;
fac[1]=1;
for(i=2; i<=18; i++) {
fac[i]=fac[i-1]*i;
}
}
void dfs(int cur, LL tmp, int step)
{
mp[step][tmp]++;
for(int i=cur+1; i<m; i++) {
dfs(i,tmp+a[i],step);
if(a[i]<=18&&step+1<=k)
dfs(i,tmp+fac[a[i]],step+1);
}
}
void dfs1(int cur, LL tmp, int step)
{
for(int i=0;i<=k-step;i++){
if(mp[i].find(s-tmp)!=mp[i].end())
ans+=mp[i][s-tmp];
}
for(int i=cur+1; i<n; i++) {
dfs1(i,tmp+a[i],step);
if(a[i]<=18&&step+1<=k)
dfs1(i,tmp+fac[a[i]],step+1);
}
}
int main()
{
int i;
init();
while(scanf("%d%d%I64d",&n,&k,&s)!=EOF) {
ans=0;
m=n/2;
for(i=0; i<n; i++) {
scanf("%d",&a[i]);
}
for(i=0;i<=k;i++) mp[i].clear();
mp[0][0]=1;
for(i=0; i<m; i++) {
dfs(i,a[i],0);
if(a[i]<=18)
dfs(i,fac[a[i]],1);
}
for(i=0; i<=k; i++) {
if(mp[i].find(s)!=mp[i].end())
ans+=mp[i][s];
}
for(i=m; i<n; i++) {
dfs1(i,a[i],0);
if(a[i]<=18)
dfs1(i,fac[a[i]],1);
}
printf("%I64d\n",ans);
}
return 0;
}
时间: 2024-10-23 22:28:39