您的位置:首页 > 其它

Codeforces525E -- Anya and Cubes 中途相遇法

2015-05-05 14:54 288 查看
题意:有n个a[0]--a[n-1]。定义一种操作:可以使数a[i]变成它的阶乘,例如5通过操作变成120。对于每一个数,可以选它,或者选它的阶乘,或者不选。要求通过 至多k次操作,使得被选的数的和为s。求方案总个数。

思路:n不超过25,时间限制是2000ms。首先可以肯定是用dfs暴力搜索,但是n又有些大,单纯暴力必然超时。这时就要用到中途相遇法,并将中间结果存下来。

AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <iomanip>
#define debug puts("xxxxxxx")
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 1<<29
typedef long long ll;
using namespace std;
const int maxn=30;
ll a[maxn],b[maxn],sum,ans;
int k,n;
void init()
{
    ans  = 0;
    b[1] = 1;
    for(int i=2; i<19; i++) b[i] = b[i-1]*i;
}
map<int,map<ll,ll> > cnt1;
map<int,map<ll,ll> > cnt2;
map<ll,ll>  ::iterator it;
void dfs1(int now,int t,ll val)
{
    if(now == n/2+1)
    {
        cnt1[t][val] ++;
        return ;
    }
    if(t<=k ) dfs1(now+1,t,val);
    if(t<=k && val+a[now]<=sum)
    {
        dfs1(now+1,t,val+a[now]);
    }
    if(t+1<=k && a[now]<19)
    {
        if(val+b[a[now]]<=sum) dfs1(now+1,t+1,val+b[a[now]]);
    }
    return ;
}
void dfs2(int now,int t,ll val)
{
    if(now==n+1)
    {
        cnt2[t][val] ++;
        return ;
    }
    if(t<=k) dfs2(now+1,t,val);
    if(t<=k && val+a[now]<=sum) dfs2(now+1,t,val+a[now]);
    if(t<k && a[now]<19)
    {
        if(val+b[a[now]]<=sum) dfs2(now+1,t+1,val+b[a[now]]);
    }
    return ;
}
int main()
{
    init();
    cin>>n>>k>>sum;
    for(int i=1; i<=n; i++) cin>>a[i];
    dfs1(1,0,0ll);
    dfs2(n/2+1,0,0ll);
    for(int i=0;i<=k;i++)
    {
        for(int j=0;j<=k;j++)
        {
            if(i+j>k) break;
            for(it = cnt1[i].begin();it!=cnt1[i].end();it++)
            {
                ans += (it->second) * cnt2[j][sum-(it->first)];
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: