In one of the games Arkady is fond of the game process happens on a rectangular field. In the game process Arkady can buy extensions for his field, each extension enlarges one of the field sizes in a particular number of times. Formally, there are n extensions, the i-th of them multiplies the width or the length (by Arkady's choice) by ai. Each extension can't be used more than once, the extensions can be used in any order.

Now Arkady's field has size h × w. He wants to enlarge it so that it is possible to place a rectangle of size a × b on it (along the width or along the length, with sides parallel to the field sides). Find the minimum number of extensions needed to reach Arkady's goal.

Input

The first line contains five integers a, b, h, w and n (1 ≤ a, b, h, w, n ≤ 100 000) — the sizes of the rectangle needed to be placed, the initial sizes of the field and the number of available extensions.

The second line contains n integers a1, a2, ..., an (2 ≤ ai ≤ 100 000), where ai equals the integer a side multiplies by when the i-th extension is applied.

Output

Print the minimum number of extensions needed to reach Arkady's goal. If it is not possible to place the rectangle on the field with all extensions, print -1. If the rectangle can be placed on the initial field, print 0.

Examples
Input
3 3 2 4 4
2 5 4 10
Output
1
Input
3 3 3 3 5
2 3 5 4 2
Output
0
Input
5 5 1 2 3
2 2 3
Output
-1
Input
3 4 1 1 3
2 3 2
Output
3
Note

In the first example it is enough to use any of the extensions available. For example, we can enlarge h in 5 times using the second extension. Then h becomes equal 10 and it is now possible to place the rectangle on the field.


  题目大意 给定一个w × h的矩形,每次可以将w或h乘上ai(ai不能重复使用,并且与顺序无关)。问至少扩充多少次可以使得这个矩形中包含一个a × b的子矩形,如果无解输出-1。

  因为 $w$ 和 $h$ 呈指数级增长,考虑爆搜。

  可以知道题目要求最少的,所以先用大的ai更划算。因此可以先将ai排一次序。

  既然是求最少,又确定是搜索,考虑 bfs。加上判重。好了这道题AC了。

  不知道为啥原来写了一个假的复杂度证明还觉得它很对?

  不难发现它涉及到的状态数不会超过下面的状态数乘 34。不过这也是一个非常松的界。

Code

 /**
* Codeforces
* Problem#799D
* Accepted
* Time: 31ms
* Memory: 2500k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; int a, b, c, d, n;
int* arr; typedef class Data {
public:
int nc;
int nd;
int step; Data():nc(), nd(), step() { }
Data(long long nc, long long nd, int step):step(step) {
this->nc = min(nc, (long long)a);
this->nd = min(nd, (long long)b);
} boolean isfin() {
return nc >= a && nd >= b;
} boolean operator < (Data b) const {
if(nc != b.nc) return nc < b.nc;
return nd < b.nd;
}
}Data; inline void init() {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &n);
arr = new int[(n + )];
for(int i = ; i <= n; i++) {
scanf("%d", arr + i);
}
} set<Data> se;
queue<Data> que;
inline int bfs(int c, int d) {
Data s(c, d, );
if(s.isfin()) return ;
while(!que.empty()) que.pop();
que.push(s);
while(!que.empty()) {
Data e = que.front();
que.pop();
// printf("e:%d %d %d\n", e.nc, e.nd, e.step); if(e.nc < a) {
Data eu(e.nc * 1LL * arr[e.step + ], e.nd, e.step + );
// printf("%d %d %d\n", eu.nc, eu.nd, eu.step);
if(eu.isfin()) return eu.step;
if(eu.step < n && !se.count(eu))
que.push(eu), se.insert(eu);
} if(e.nd < b) {
Data eu(e.nc, e.nd * 1LL * arr[e.step + ], e.step + );
// printf("%d %d %d\n", eu.nc, eu.nd, eu.step);
if(eu.isfin()) return eu.step;
if(eu.step < n && !se.count(eu))
que.push(eu), se.insert(eu);
}
}
return -;
} inline void solve() {
sort(arr + , arr + n + , greater<int>());
while(n && arr[n] == ) n--;
int res1 = bfs(c, d), res2 = bfs(d, c);
if(res1 == - && res2 == -) puts("-1");
else if(res1 == - || res2 == -) printf("%d\n", max(res1, res2));
else printf("%d\n", min(res1, res2));
} int main() {
init();
solve();
return ;
}

Field expansion(bfs)

  当 $a_i$ 大于2时,因为 $\log_3 10^5 \leqslant 11$,所以暴力枚举的次数不会超过 $2^{22}$,不过这是很松的界了,因为一边满了后不会再往这边放了。当 $a_i$ 等于2时,可以直接判。

Code

 /**
* Codeforces
* Problem#799D
* Accepted
* Time: 15ms
* Memory: 2428k
*/
#include <bits/stdc++.h>
using namespace std;
#define smin(a, b) a = min(a, b)
typedef bool boolean;
const signed int inf = 1e9; int a, b, c, d, n;
int* arr; inline void init() {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &n);
arr = new int[(n + )];
for(int i = ; i <= n; i++) {
scanf("%d", arr + i);
}
} int res = ;
int deplimit = ;
void dfs(int dep, int nc, int nd) {
// printf("%d %d %d\n", dep, nc, nd);
if(nc >= a && nd >= b) {
deplimit = dep, smin(res, dep);
// cout << dep << endl;
return;
}
if(dep == n) return;
if(arr[dep + ] == ) {
deplimit = dep;
while(nc < a && dep < n) nc <<= , dep++;
while(nd < b && dep < n) nd <<= , dep++;
if(nc < a || nd < b) return;
// cout << dep << endl;
smin(res, dep);
}
if(dep == deplimit) return;
long long nnc = nc * 1LL * arr[dep + ], nnd = nd * 1LL * arr[dep + ];
if(nc < a) dfs(dep + , smin(nnc, (long long)a), nd);
if(nd < b) dfs(dep + , nc, smin(nnd, (long long)b));
} inline void solve() {
sort(arr + , arr + n + , greater<int>());
while(n && arr[n] == ) n--;
dfs(, c, d), dfs(, d, c);
printf("%d\n", (res < ) ? (res) : (-));
} int main() {
init();
solve();
return ;
}

最新文章

  1. CentOS:Yum源的配置
  2. 灾难 bzoj 2815
  3. vs2010配置boost编程环境(照抄并简化)
  4. ProGuard代码混淆技术详解
  5. 剑指Offer 用两个栈实现队列
  6. osg 路径 动画 效果
  7. NOIP200205均分纸牌
  8. Linux目录初识
  9. Java与WCF交互(一)补充:用WSImport生成WSDL的Java客户端代码
  10. usaco /the second wave
  11. Linux下如何选择文件系统:EXT4、Btrfs 和 XFS
  12. 玩转html5(一)-----盘点html5新增的那些酷酷的input类型和属性
  13. js 对象类型 (对象的属性 ,对象的方法) this 关键字
  14. 【DP系列学习一】简单题:kickstart2017 B.vote
  15. 微信小程序之最简单的Demo设计使用
  16. 零基础学Python--------第8章 模块
  17. Kali学习笔记26:OWASP_ZAP
  18. clipboard.js -- js实现将文本复制到剪贴板的方法
  19. highcharts中数据列点击事件
  20. 最全的select加锁分析(Mysql)

热门文章

  1. android js与控件交互初探。
  2. Redux 笔记详解
  3. cocos2dx 3.x(游戏中的储存-UserDefault)
  4. (4)Python3笔记 之 流程控制
  5. /*使用PHP创建一个数组,保存5個员工的信息(ename/sex/salary/birthday/pic)*/
  6. 恢复Windows10应用商店
  7. hdu4870 高斯消元
  8. Mini-Batch 、Momentum、Adam算法的实现
  9. P2800 又上锁妖塔
  10. 前端框架VUE----vue的使用