Codeforces 525E Anya and Cubes

题意:给你n(25)个数,任选几个数 ,你最多可以对任选的几个数中的 K个数进行操作,操作是将 这个数变为它的阶乘,你选出来的数经过操作以后 等于 s的种类数有多少。

解题思路:看到这题的时候没什么思路,想想水一发dp  ,dp[i][j][k]<map>,就想到了这个四维的DP,但是显然这是会挂掉的。因为情况太多了,最多有 3^n种。

那么需要是什么方法呢。那就是折半了,因为我们只需要找到一个值, 而全部DP的话会产生太多的值了,而这大部分值都不是我们需要的。所以就把n个数分成两堆去处理,然后用中间值凑出s,这样复杂度就会少很多.

解题代码:

 1 // File Name: e.cpp
 2 // Author: darkdream
 3 // Created Time: 2015年03月27日 星期五 01时21分34秒
 4
 5 #include<vector>
 6 #include<list>
 7 #include<map>
 8 #include<set>
 9 #include<deque>
10 #include<stack>
11 #include<bitset>
12 #include<algorithm>
13 #include<functional>
14 #include<numeric>
15 #include<utility>
16 #include<sstream>
17 #include<iostream>
18 #include<iomanip>
19 #include<cstdio>
20 #include<cmath>
21 #include<cstdlib>
22 #include<cstring>
23 #include<ctime>
24 #define LL long long
25
26 using namespace std;
27 int n ,m ;
28 LL s ;
29 LL a[100];
30 LL b[100];
31 map<int,map<LL,LL> > mpa;
32 map<int,map<LL,LL> > mpb;
33 map<LL,LL>::iterator tt;
34 int li;
35 void dfs(int p ,int k,LL v,map<int,map<LL,LL> > &tmp)
36 {
37     //printf("%d %d %I64d\n",p,k,v);
38     if(k > m)
39         return;
40     if(p == li + 1)
41     {
42       tmp[k][v] += 1 ;
43       return;
44     }
45     if(v + a[p] <= s)
46         dfs(p+1,k,v+a[p],tmp);
47     if(a[p] <= 18 && v + b[p] <= s)
48         dfs(p+1,k+1,v+b[p],tmp);
49     dfs(p+1,k,v,tmp);
50 }
51 int main(){
52     scanf("%d %d %I64d",&n,&m,&s);
53     for(int i = 1;i <= n;i ++)
54     {
55        scanf("%I64d",&a[i]);
56     }
57     sort(a+1,a+1+n);
58     for(int i = 1;i <= n;i ++)
59     {
60        if(a[i] <= 18)
61        {
62          b[i] = 1;
63          for(int j = 1;j <= a[i]; j ++)
64          {
65            b[i] *= j;
66          }
67        }
68     }
69      li = n/2;
70     dfs(1,0,0,mpa);
71     li = n;
72     //puts("***");
73     dfs(n/2+1,0,0,mpb);
74     LL sum = 0 ;
75     for(int i = 0 ;i <= m;i ++)
76     {
77         for(int j = 0 ;j + i <= m;j ++)
78         {
79            for(tt = mpa[i].begin(); tt != mpa[i].end();tt++)
80            {
81               sum += (mpb[j][s - tt->first]) * (tt->second);
82     //          printf("***%d %I64d %I64d %I64d\n",j,s-tt->first,mpb[j][s-tt->first],tt->second);
83            }
84         }
85     }
86     printf("%I64d\n",sum);
87     return 0;
88 }

时间: 2024-10-08 00:39:53

Codeforces 525E Anya and Cubes的相关文章

Codeforces 525E Anya and Cubes 中途相遇法

题目链接:点击打开链接 题意: 给定n个数,k个感叹号,常数S 下面给出这n个数. 目标: 任意给其中一些数变成阶乘,至多变k个. 再任意取一些数,使得这些数和恰好为S 问有多少方法. 思路: 三进制状压,中途查找. #include <stdio.h> #include <vector> #include <algorithm> #include <iostream> #include <cmath> #include <map>

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

说的是给了n个立方体,立方体从1标号到n,每个立方体上有一个数字, 你有 k 个机会 使得其中 k个数位他们自己的阶乘,(自然使用可以少于k次机会,每个立方体最多被使用1次) ,那么求出你从这n个立方体重选出任意个立方体使得 他们的和为S n<25 可以知道直接使用n去枚举自然受不了, 我们将n个数字分为两部分来算,前面n/2个数字 我们枚举他们使用j次可以得到的数,然后后面的n-n/2个数再次使用这个方法,直接在dfs枚举的时候进行判断S-s 在前一个钟是否出现过,出现过就加起来. 分块处理

codeforces 525 E Anya and Cubes 中途相遇法

codeforces 525 E Anya and Cubes 中途相遇法 题意: 给出n个数a1,a2,...,an,要求从中选出一些数,可以把其中最多k个变成它自己的阶乘,然后选出的数求和,问最后和等于s的选法有多少种. 限制: 1 <= n <= 25; 0 <= k <= n; 1<= s <= 1e16; 1 <= ai <= 1e9 思路: 一般数据量20~30都会考虑中途相遇法,就是折半暴力. ps:用三进制暴力会比直接深搜多一个常数10,因为

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

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

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

大意: 给定$n$元素序列$a$, 可以任选不超过$k$个$a_i$变换为$a_i!$, 求变换后任选若干元素和为S的方案数. 分成两块暴搜, 复杂度$O(3^{\frac{n}{2}})$ #include <iostream> #include <algorithm> #include <cstdio> #include <unordered_map> #define REP(i,a,n) for(int i=a;i<=n;++i) using n

Codeforces Round #297 (Div. 2)E. Anya and Cubes

题目链接:http://codeforces.com/problemset/problem/525/E 题意: 给定n个数,k个感叹号,常数S 下面给出这n个数. 目标: 任意给其中一些数变成阶乘,至多变k个. 再任意取一些数,使得这些数和恰好为S 问有多少方法. 思路: 三进制状压,0代表不取,1代表取阶乘,2代表直接取: 中途查找,节约空间: 代码如下: #include<cstdio> #include<cstring> #include<iostream> #i

codeforces 297 E. Anya and Cubes

参考题解:http://blog.csdn.net/u014800748/article/details/44680613 题意: 给你n个cube,从里边最多选k个数,求选定的数中,求有多少数,或这个数的阶乘,的和等于S的个数数. 思路: 本题利用双向查找解决.双向查找一般用于求若干个数之和相加等于一个固定值的题目.一般方法是将n个数分为两部分:1~n/2和n/2+1到n,然后枚举出两部分的所有可能的结果,最后利用二分查找看第一部分的结果是否存在于第二部分中.本题也是让找一些数之和等于S,这个

CodeForces 508C Anya and Ghosts

Anya and Ghosts Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 508C Description Anya loves to watch horror movies. In the best traditions of horror, she will be visited by m ghosts toni