枚举和二分

一切都从头开始,今天先复习枚举和二分。枚举就不多说了,说一下二分,二分其实是分治的一种,是当n=2是的一种情况,也叫二分查找(折半查找),二分查找速度快,比你从头一个一个的查可快多了,二分查找是每次把集合一分为二,看你要找的是在前一半还是后一半,如果在前一半再把前一半一分为二以此类推知道找到你想要的,在后一半同理。二分查找的条件之一是元素表必须是有序表。下面两个模板

 1 int l,r,res;//l为左边界,r为右边界,具体值要看目,res为记录mid值的
 2 while(l<=r){//循环条件很重要,当l>r时循环结束,res记录的是l=r时的值
 3     int mid=(l+r)/2;
 4     if(ok(mid)){//ok函数要看题目具体设计
 5         l=mid+1;//选哪个要看题
 6         //r=mid-1;
 7         res=mid;
 8     }
 9     else
10         r=mid-1;
11         //l=mid+1;
12 }
 1 //第一个是整形二分,下面是浮点型二分
 2 #define eps 1e-8 //定义宏eps,eps是精度
 3 double l,r;
 4 while(l+eps<r){
 5     double mid=(l+r)/2.0;//注意除的是2.0
 6     if(ok(mid)){
 7         l=mid;//注意没有减一或加一
 8         //r=mid;
 9     }
10     else
11         r=mid;
12         //l=mid;
13 }前两天刚做的一个题。题意是给你个整形变量n查找从1~n内的special number个数(0<n<=10000000),special number就是这个数不能有重复的数字出现也不呢不过有前导0,比如023,1124都不是,1234就是。这个题不难但是有时间限制所以关键是看判断是special number 的优化。
 1 #include<cstdio>
 2 #include<cstring>
 3 #define maxn 10000000
 4 using namespace std;
 5 int a[5000000];///存的是special number
 6 ///判断是否是特别数
 7 bool ok(int x){
 8     bool vis[10],flag=true;///假设这个数最大有10位,vis的作用就是记录他的每位数是否出现过
 9     memset(vis,false,sizeof(vis));//先初始化为没出现过
10     while(x){
11         int tmp=x%10;///取每位数
12         x=x/10;
13         if(vis[tmp]){
14             flag=false;///如果这位数曾经出现过则这个数就不是特别数
15             break;
16         }
17         vis[tmp]=true;///否则记录出现过
18     }
19     return flag;
20 }
21 int main(){
22     memset(a,0,sizeof(a));
23     int cnt=0;
24     for(int i=1; i<=maxn; i++){///先把所有的特别数按顺序存储在数组里,这就是枚举
25             if(ok(i))
26                 a[cnt++]=i;///cnt+1是所有特别数的个数
27     }
28     int n;
29     while(~scanf("%d",&n)){
30         int l=0,r=cnt-1,res;
31         if(n<=1){
32             printf("%d\n",0);
33             continue;
34         }
35         while(l<=r){///分的是下标,因为小于n的特别数个数就是小于n的树中最大特别数的下标+1。(好好想想,因为特别数已经按顺序存储)
36             int mid=(l+r)/2;
37             if(a[mid]<n){
38                 l=mid+1;
39                 res=mid;
40             }
41             else
42                 r=mid-1;
43         }
44         printf("%d\n",res+1);
45     }
46 }
				
时间: 2024-10-23 22:17:51

枚举和二分的相关文章

枚举,二分

二分模板 ① 普通的整数二分 int l, r, res; while(l <= r){ int mid = (l + r) / 2; if (ok (mid)){ res = mid; r = mid - 1;  } else{ l = mid + 1; // 满足条件的最小值 } } 精度精确型二分 const double eps = 1e-7; double l, r; while (l + eps < r){ double mid = (l + r) / 2.0; if (ok (m

【POJ2699】The Maximum Number of Strong Kings 枚举(二分)+网络流check、

题意: 有n个人,两两都有比赛,然后有每个人的胜场次数. 规定把比自己胜场次数多的人都赢了的就是strong(weak) king (vegetables) (why i say that they are so weak? :****,how do you think a person who beat the heroes but defeated at the dogface? ) 让你安排比赛,问最多有多少个strongking? 题解: 首先(有人说)能证如果有k个sk,那么一定可以是

[2017浙工大之江学院决赛 E] qwb和李主席(折半枚举,二分)

题目链接:http://115.231.222.240:8081/JudgeOnline/problem.php?cid=1005&pid=4 题意:把一个数组拆成两部分,使得两个集合分别的和的差的绝对值最小. 做过类似的,用01背包,求sum/2容量下的最大价值,这样可以拆成两个集合,并且符合题意. 但是这题浮点数,而且物品价值1e9,不能背包了. n<=36,也不能直接枚举. 可以把n个数拆成两部分,先枚举一部分的组合情况,把和求出来,再枚举另一部分,枚举到一个和x后在第一部分的和里二分

Codeforces 912 E.Prime Gift (折半枚举、二分)

题目链接:Prime Gift 题意: 给出了n(1<=n<=16)个互不相同的质数pi(2<=pi<=100),现在要求第k大个约数全在所给质数集的数.(保证这个数不超过1e18) 题解: 如果暴力dfs的话肯定超时间,其实给的n数据范围最大是16是一个很奇妙的数(一般折半枚举基本上是这样的数据范围@.@-).所以想到折半枚举,把所有的质数分成两份求出每份中所有小于1e18的满足条件的数.然后二分答案,写cheak函数时遍历第一个集合,对第二个集合二分(折半枚举基本上这个套路).

1189. [HNOI2007]紧急疏散EVACUATE【最大流+枚举或二分】

Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间.已知门 一定在房间的边界上,并且边界上不会有空地.最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都 可以向上下左右四个方向移动一格,当然他也可以站着不动.疏散开始后,每块空地上就没有人数限制了(也就是 说每块空地可以同时站无数个人).但是,由于门很窄,每一秒

Codeforces 888E:Maximum Subsequence(枚举,二分)

You are given an array a consisting of n integers, and additionally an integer m. You have to choose some sequence of indices \(b_1,?b_2,?...,?b_k (1?≤?b_1?<?b_2?<?...?<?b_k?≤?n)\) in such a way that the value of \(\sum^{k}_{i=1}a_{b_i}\) is maxi

POJ-2785 4 Values whose Sum is 0(折半枚举 sort + 二分)

题目链接:http://poj.org/problem?id=2785 题意是给你4个数列.要从每个数列中各取一个数,使得四个数的sum为0,求出这样的组合的情况个数. 其中一个数列有多个相同的数字时,把他们看作不同的数字. 做法是把前两个数列和的值存在一个数组(A)中 , 后两个数列的和存在另一个数组(B)中 , 数组都为n^2 . 然后将B数组sort一下 , 将A数组遍历 , 二分查找一下B数组中与A数组元素和为0的个数 . 有个注意的点是万一A数组都是0 , 而B数组都为0的情况(还有其

Squares-暴力枚举或者二分

B - Squares Time Limit:3500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2002 Description A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a po

[HDOJ5878]I Count Two Three(暴力枚举,二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5878 两种做法 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #inc