E. Anya and Cubes (CF #297 (Div. 2) 折半搜索)

E. Anya and Cubes

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Anya loves to fold and stick. Today she decided to do just that.

Anya has n cubes lying in a line and numbered from 1 to n from
left to right, with natural numbers written on them. She also has kstickers with exclamation marks. We know that the number of stickers does not exceed
the number of cubes.

Anya can stick an exclamation mark on the cube and get the factorial of the number written on the cube. For example, if a cube reads 5, then after the sticking it
reads 5!, which equals 120.

You need to help Anya count how many ways there are to choose some of the cubes and stick on some of the chosen cubes at most kexclamation marks so that
the sum of the numbers written on the chosen cubes after the sticking becomes equal to S. Anya can stick at most one exclamation mark on each cube. Can
you do it?

Two ways are considered the same if they have the same set of chosen cubes and the same set of cubes with exclamation marks.

Input

The first line of the input contains three space-separated integers nk and S (1?≤?n?≤?25, 0?≤?k?≤?n, 1?≤?S?≤?1016) — the
number of cubes and the number of stickers that Anya has, and the sum that she needs to get.

The second line contains n positive integers ai (1?≤?ai?≤?109) — the
numbers, written on the cubes. The cubes in the input are described in the order from left to right, starting from the first one.

Multiple cubes can contain the same numbers.

Output

Output the number of ways to choose some number of cubes and stick exclamation marks on some of them so that the sum of the numbers became equal to the given number S.

Sample test(s)

input

2 2 30
4 3

output

1

input

2 2 7
4 3

output

1

input

3 1 1
1 1 1

output

6

Note

In the first sample the only way is to choose both cubes and stick an exclamation mark on each of them.

In the second sample the only way is to choose both cubes but don‘t stick an exclamation mark on any of them.

In the third sample it is possible to choose any of the cubes in three ways, and also we may choose to stick or not to stick the exclamation mark on it. So, the total number of ways is six.

题意:给你n个数,k个魔法棒,s为所求的数,然后让你找有多少种方法,能够使的这n个数之和为s,其中一个魔法棒可以使的一个数变成他的阶乘。

思路:采用折半搜索,自己太渣。。请看这位大神详解~

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef __int64 ll;
using namespace std;

typedef pair<ll,ll>P;
map<P,ll>a,b;
ll n,k,s;
ll p[30];
ll val[30];

void init()
{
    int i;
    p[0]=p[1]=1;
    FRE(i,2,20)
        p[i]=p[i-1]*i;
}

void dfs(ll pos,ll num,ll kk)
{
    if (num>s||kk>k) return ;
    if (pos>n/2)
    {
        a[P(num,kk)]++;
        return ;
    }
    dfs(pos+1,num+val[pos],kk);
    dfs(pos+1,num,kk);
    if (val[pos]<=20)
        dfs(pos+1,num+p[val[pos]],kk+1);
    return ;
}

void DFS(ll pos,ll num,ll kk)
{
    if (num>s||kk>k) return ;
    if (pos>n)
    {
        b[P(num,kk)]++;
        return ;
    }
    DFS(pos+1,num+val[pos],kk);
    DFS(pos+1,num,kk);
    if (val[pos]<=20)
        DFS(pos+1,num+p[val[pos]],kk+1);
    return ;
}

int main()
{
    ll i,j;
    init();
    while (~scanf("%I64d%I64d%I64d",&n,&k,&s))
    {
        a.clear();
        b.clear();
        FRE(i,1,n)
            scanf("%I64d",&val[i]);
        dfs(1,0,0);
        DFS(n/2+1,0,0);
        ll ans=0;
        for (map<P,ll>::iterator it=a.begin();it!=a.end();it++)
        {
            int aa=(*it).first.second;
            for (int bb=0;aa+bb<=k;bb++)
            {
                if (b.count(make_pair(s-(it->first.first),bb)))
                    ans+=(it->second*b[make_pair(s-(it->first.first),bb)]);
            }
        }
        pf("%I64d\n",ans);
    }
    return 0;
}
时间: 2024-10-05 13:55:21

E. Anya and Cubes (CF #297 (Div. 2) 折半搜索)的相关文章

Codeforces Round #297 (Div. 2) E题. Anya and Cubes (中途相遇法)

题目地址:Anya and Cubes 比赛的时候居然没想起中途相遇法...这题也是属于想起来就很简单系列. 中途相遇法也叫折半搜索.就是处理前一半,把结果储存起来,再处理后一半,然后匹配前一半存储的结果. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib

Codeforces Round #297 (Div. 2) (ABCDE题解)

比赛链接:http://codeforces.com/contest/525 算是比较简单的一场了,拖了好久现在才补 A. Vitaliy and Pie time limit per test:2 seconds memory limit per test:256 megabytes After a hard day Vitaly got very hungry and he wants to eat his favorite potato pie. But it's not that sim

CF #371 (Div. 2) C、map标记

1.CF #371 (Div. 2)   C. Sonya and Queries  map应用,也可用trie 2.总结:一开始直接用数组遍历,果断T了一发 题意:t个数,奇变1,偶变0,然后与问的匹配. #include<bits/stdc++.h> #define max(a,b) a>b?a:b #define F(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF

BFS Codeforces Round #297 (Div. 2) D. Arthur and Walls

题目传送门 1 /* 2 题意:问最少替换'*'为'.',使得'.'连通的都是矩形 3 BFS:搜索想法很奇妙,先把'.'的入队,然后对于每个'.'八个方向寻找 4 在2*2的方格里,若只有一个是'*',那么它一定要被替换掉 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <algorithm> 9 #include <cstring> 10 #include <queue> 1

CF#247(Div. 2)部分题解

引言: 在软件项目中,Maven提供了一体化的类库管理系统,非常实用.但是,如果新增的类库jar在网络上无法获取到,如何在本地按照Maven的规则添加进来呢?本文将通过一个小例子展示新增过程. 背景介绍: 一个Maven管理的Java项目,提供一个系统级别的POM.xml,其中定义了整个项目使用的类库. 需求: 需要添加一个自定义的类库到当前项目中.假定当前的类库文件名为:abc.jar.. 如何将类库添加进来? 1.  找到当前Maven的Repository类库位置 一般默认情况下,在win

CF #375 (Div. 2) D. bfs

1.CF #375 (Div. 2)  D. Lakes in Berland 2.总结:麻烦的bfs,但其实很水.. 3.题意:n*m的陆地与水泽,水泽在边界表示连通海洋.最后要剩k个湖,总要填掉多少个湖,然后输出. #include<bits/stdc++.h> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,s

CF #374 (Div. 2) D. 贪心,优先队列或set

1.CF #374 (Div. 2)   D. Maxim and Array 2.总结:按绝对值最小贪心下去即可 3.题意:对n个数进行+x或-x的k次操作,要使操作之后的n个数乘积最小. (1)优先队列 #include<bits/stdc++.h> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(

cf #254 (Div. 2)

a题 #include<stdio.h> #include<string.h> char c[101][101]; int main() { long n,m,i,j; scanf("%ld%ld",&n,&m); gets(c[0]); for(i=1;i<=n;i++) gets(c[i]); for(i=1;i<=n;i++) { for(j=0;j<m;j++) if(c[i][j]=='-') printf("

贪心 Codeforces Round #297 (Div. 2) C. Ilya and Sticks

题目传送门 1 /* 2 题意:给n个棍子,组成的矩形面积和最大,每根棍子可以-1 3 贪心:排序后,相邻的进行比较,若可以读入x[p++],然后两两相乘相加就可以了 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <cstring> 8 #include <cmath> 9 using namespace std; 10 11 typedef long long ll; 12 13 co