题目

Source

http://codeforces.com/contest/525/problem/E

Description

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 k stickers 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 k exclamation 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 n, k 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 Input

2 2 30
4 3
2 2 7
4 3
3 1 1
1 1 1

Sample Output

1
1
6

分析

题目大概说有n个数,从中选出若干个数,可以再从选择的数中选择不超过k个数让它们变为自身的阶乘,问有几种方案使得选出来的若干个数的和等于S。

将n个数分成两边,左边dfs不选、选、选且变为阶乘搜出所有方案,用map统计各个和的情况;右边一样,利用map更新答案。
不过,由于最后还要枚举更新答案,超时了;把左边搜索的数量增加一点,变为min(n/2+2,n)就过了。
看了下官方题解,题解说先用count()判断map有没有再用这样会快,果然快了1倍。

代码

#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std; long long S;
int n,m,a[26]; long long fact[20]={1}; long long ans; map<long long,int> cnt[26];
int tmp;
void dfs1(int x,int y,long long s){
if(s>S || y>m) return;
if(x==tmp){
++cnt[y][s];
return;
}
dfs1(x+1,y,s);
dfs1(x+1,y,s+a[x]);
if(a[x]<19) dfs1(x+1,y+1,s+fact[a[x]]);
} void dfs2(int x,int y,long long s){
if(s>S || y>m) return;
if(x==n){
for(int i=0; i+y<=m; ++i){
if(cnt[i].count(S-s)) ans+=cnt[i][S-s];
}
return;
}
dfs2(x+1,y,s);
dfs2(x+1,y,s+a[x]);
if(a[x]<19) dfs2(x+1,y+1,s+fact[a[x]]);
} int main(){
for(int i=1; i<20; ++i){
fact[i]=fact[i-1]*i;
}
scanf("%d%d%lld",&n,&m,&S);
for(int i=0; i<n; ++i){
scanf("%d",a+i);
}
tmp=min(n,n/2+2);
dfs1(0,0,0);
dfs2(tmp,0,0);
printf("%lld\n",ans);
return 0;
}

Codeforces525E Anya and Cubes(双向搜索)的更多相关文章

  1. Codeforces Round #297 (Div. 2)E. Anya and Cubes 折半搜索

    Codeforces Round #297 (Div. 2)E. Anya and Cubes Time Limit: 2 Sec  Memory Limit: 512 MBSubmit: xxx  ...

  2. Anya and Cubes 搜索+map映射

    Anya loves to fold and stick. Today she decided to do just that. Anya has n cubes lying in a line an ...

  3. Codeforces 525E Anya and Cubes

    http://codeforces.com/contest/525/problem/E 题意: 有n个方块,上面写着一些自然数,还有k个感叹号可用.k<=n 你可以选任意个方块,然后选一些贴上感 ...

  4. Anya and Cubes CodeForces - 525E (双端搜索)

    大意: 给定$n$元素序列$a$, 可以任选不超过$k$个$a_i$变换为$a_i!$, 求变换后任选若干元素和为S的方案数. 分成两块暴搜, 复杂度$O(3^{\frac{n}{2}})$ #inc ...

  5. codeforces E - Anya and Cubes 分块处理 暴力搜索

    说的是给了n个立方体,立方体从1标号到n,每个立方体上有一个数字, 你有 k 个机会 使得其中 k个数位他们自己的阶乘,(自然使用可以少于k次机会,每个立方体最多被使用1次) ,那么求出你从这n个立方 ...

  6. CF525E Anya and Cubes(meet in the middle)

    题面 给你\(n\)个数,\(n\le 26\)初始序列为\(a_i,0\le a_i\le 10^9\) 你有\(k\)个\(!\),每个\(!\)可以使序列中的一个数变成\(a_i!\) 例如\( ...

  7. [Codeforces Round #297 Div. 2] E. Anya and Cubes

    http://codeforces.com/contest/525/problem/E 学习了传说中的折半DFS/双向DFS 先搜前一半数,记录结果,然后再搜后一半数,匹配之前结果. #include ...

  8. Codeforces 525E Anya and Cubes 中途相遇法

    题目链接:点击打开链接 题意: 给定n个数.k个感叹号,常数S 以下给出这n个数. 目标: 随意给当中一些数变成阶乘.至多变k个. 再随意取一些数,使得这些数和恰好为S 问有多少方法. 思路: 三进制 ...

  9. 【Henu ACM Round#18 E】Anya and Cubes

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 每个数字有3种选择. 1.选中它. 2.选中它且加阶乘符号 3.不选中它(即计算和的时候不考虑它) 如果我们直接暴力写的话复杂度是\ ...

随机推荐

  1. [Unity3d]游戏中子弹碰撞的处理

    如果使用Collider+Rigidbody的方式来处理,则它是每一帧进行判定碰撞:如果子弹过快导致碰撞发生在2帧之间,则会导致无法捕获这个碰撞效果 基于上述原因,我们要使用射线Raycast进行子弹 ...

  2. marquee标签,好神奇啊...

    <html><body><div style="height:190; margin-top:10; margin-bottom:10; width:96%; ...

  3. [NHibernate]立即加载

    目录 写在前面 文档与系列文章 立即加载 一个例子 总结 写在前面 上篇文章介绍了nhibernate延迟加载的相关内容,简单回顾一下延迟加载,就是需要的时候再去加载,需要的时候再向数据库发出sql指 ...

  4. jQuery包装集

    jQuery包装集指的是通过$()方法返回的一个元素集,这跟一般的javascript数组有所区别, 包装集在后者的基础上还有一些初始化的函数和属性. 我们可以对二者进行一个比较: jsdiv = d ...

  5. Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解

    C 编程中,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般 ...

  6. Linux进程间通信(八):流套接字 socket()、bind()、listen()、accept()、connect()、read()、write()、close()

    前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进程.通常我们使用socket进行网络编 ...

  7. mount -t nfs 的使用

    服务安装:1. 在VMware Ubuntu中安装NFS服务: sudo apt-get install nfs-kernel-server2. 安装成功会出现配置文件/etc/exports. ls ...

  8. 记录一下两个比较常用的md5加密算法

    第一个,计算字符串的md5值 public static String getMD5(String s){ String newString = null; byte[] inputByteArray ...

  9. 十一. 一步步破解JEB 2.0demo版一

    字符串解密算法还愿 jeb.jar为核心功能,所以主要分析这个 1. jar转dex在使用jeb分析 Android\sdk\build-tools\23.0.3 dx.bat --dex --out ...

  10. Newton's method 分析

    大家都知道对于合理的函数和合理的值域牛顿迭代法是二次收敛(quadratic covergence)的(收敛速度定义见 https://en.wikipedia.org/wiki/Rate_of_co ...