sduacm2016级暑假集训 二分&尺取&三分
来源:互联网 发布:人工智能的英语怎么写 编辑:程序博客网 时间:2024/06/15 05:26
比赛地址
密码:acm2016
A - Can you solve this equation? (HDU2199)
题目链接
【题意】
给出实数y,求方程8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y在0~100范围内的解。
精确到1e-4。
【分析】
令f(x)=8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 -Y,可以发现这个函数满足单调性,故可以二分答案求解。
【Code】
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>using namespace std;#define INF 0x3f3f3f3ftypedef long long LL;const double PI = acos(-1.0);const int MAX_N = 100000 + 10;const double EPS = 1e-10;double y;double calc(double x){ return 8*x*x*x*x + 7*x*x*x + 2*x*x + 3*x + 6;}int main(){ int Case; scanf("%d",&Case); while (Case--){ scanf("%lf",&y); double L = 0, R = 100, mid; for (int i = 0; i < 100; i++){ mid = (R+L) / 2; //printf("%.2f %.5f\n",mid, calc(mid)); if (calc(mid) + EPS < y) L = mid; else R = mid; } if ((L <= EPS )||(R + EPS>= 100)){ printf("No solution!\n"); continue; } printf("%.4f\n",L); }}
B - The Meeting Place Cannot Be Changed (Codeforces 780B)
题目链接
【题意】
给n个人,第i个人在x[i]这个位置,他的速度为v[i],在第t分钟能到的范围为
[x[i] - t * v[i], x[i] + t * v[i]],求它们相聚的最短时间。
【分析】
也是很明显如果在第t分钟可以相聚,在大于t的时间也一定可以相聚。
然后二分时间,然后O(n)的判断是否可行,注意二分L,R的边界。
判断是否可行就是看是否有一个点能让所有人都到这个点就好,只需要lmax>=rmin就好。
【Code】
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>using namespace std;#define INF 0x3f3f3f3ftypedef long long LL;const double PI = acos(-1.0);const int MAX_N = 100000 + 10;const double EPS = 1e-8;double x[MAX_N], v[MAX_N];int n;bool check(double t){ double x1 = 1e9, x2 = 0; for (int i = 0;i < n;i++){ double l = x[i] - v[i]*t; double r = x[i] + v[i]*t; //l = max(l,1); r = min(r,1e9); x1 = min(x1,r); x2 = max(x2,l); } if (x2<=x1) return true; return false;}int main(){ scanf("%d",&n); for (int i = 0; i < n; i++) scanf("%lf",&x[i]); for (int i = 0; i < n; i++) scanf("%lf",&v[i]); double L = 0.0, R = 1e9, mid; for (int i = 0; i < 1000; i++){ mid = (L + R) / 2; if (check(mid)) R = mid; else L = mid; //printf("%d %.12f\n",check(mid),mid); } printf("%.12f\n",L); return 0;}
C - Cable master (POJ1064)
题目链接
【题意】
有n个绳子,要得到k份长度相等的绳子,问绳子最长能有多长。
【分析】
显然答案具有单调性,然后二分判断就好。注意输出不能直接输出答案,那样会四舍五入可以*100取整再 *0.01
【Code】
#include <cstdio>#include <cstring>#include <cmath>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3ftypedef long long LL;const int MAX_N = 20000;double a[MAX_N];int n,k;bool check(double mid){ int cnt = 0; for (int i = 0;i < n;i++){ cnt += (int) (a[i]/mid); if (cnt>=k) return true; } return false;}int main(){ scanf("%d%d",&n,&k); double l = 0, r = 0 , mid; for (int i = 0;i < n;i++){ scanf("%lf", &a[i]); r = max(r,a[i]); } for (int i = 0;i < 100;i++){ mid = (r + l) /2; if (check(mid)) l = mid; else r = mid; //printf("%d %.5f\n", check(mid), mid); } printf("%.2f\n",(int)(l*100)*0.01); return 0;}
D - Median (POJ3579)
题目链接
【题意】
给出N个数,X1到XN,会有M个数对Xi,Xj 构成|Xi - Xj|(1<=i
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define INF 0x3f3f3f3ftypedef long long LL;const int MAX_N = 100000 + 10;int a[MAX_N];int n,tmp;bool check(int x){ int cnt = 0; for(int i = 0;i < n;i++) { int t = upper_bound(a, a + n, a[i] + x) - a; cnt += t - i - 1; } if(cnt >= tmp) return true; return false;}int main(){ while(~scanf("%d", &n)){ for (int i = 0;i < n;i++) scanf("%d", &a[i]); sort(a, a + n); int m = n * (n - 1) / 2; tmp = (m + 1) / 2; int l = 0, r = a[n - 1] - a[0]; int ans; while(l <= r) { int mid = (l + r) >> 1; if (check(mid)){ ans = mid; r = mid - 1; }else l = mid + 1; } printf("%d\n", ans); } return 0;}
E - NPY and shot(HDU5144)
题目链接
【题意】
给出初始高度和初速度,求不同角度斜抛运动可得的最长距离
【分析】
设角度为p
根据相关物理可知
vx = v * cos(p);
vy = v * sin(p);
t = (vy + sqrt(vy * vy + 2 * g * h)) / g
x = vx * t;
可以看出x随着p的变化先增后减,所以可以三分求解.
【Code】
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>using namespace std;#define INF 0x3f3f3f3ftypedef long long LL;const double PI = acos(-1.0);const int MAX_N = 100000 + 10;const double g = 9.8;double h,v;double Dist(double degree){ double vx = v * cos(degree); double vy = v * sin(degree); double t = (vy + sqrt(vy * vy + 2 * g * h)) / g; return t * vx ;}int main(){ int Case; scanf("%d",&Case); while (Case--){ scanf("%lf%lf",&h,&v); double L = 0, R = 90; double mid1, mid2, ans = 0; while (fabs(R-L)>=1e-6){ mid1 = (L * 2 + R) / 3; mid2 = (L + 2 * R) / 3; double L1 = Dist(mid1); double L2 = Dist(mid2); ans = max(ans, max(L1, L2)); if (L2+1e-6>L1) L = mid1; else R = mid2; } printf("%.2f\n",ans); }}
F - Robin Hood (Codeforces 671B)
题目链接
【题意】
有n个人,每个人a[i]个物品,进行k次操作,每次都从最富有的人手里拿走一个物品给最穷的人。
问k次操作以后,物品最多的人和物品最少的人相差几个物品
【分析】
如果次数足够多的话,最后的肯定在平均值上下,小的最多被补到sum/n,大最多减少到sum/n,或者sum/n+1。
然后就二分最小值,看所有小的是否能在k次被填满 ;
二分最大值,看所有大的是否都在k次被抹平。
然后就是二分的写法,小和大的不一样,需要加等号,避免死循环。
【Code】
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>using namespace std;#define INF 0x3f3f3f3ftypedef long long LL;const double PI = acos(-1.0);const int MAX_N = 500000 + 10;int n, k;int a[MAX_N];LL calc1(int mid){ LL tot = 0; for (int i = 0;i < n;i++) if (a[i]<=mid) tot += mid - a[i]; return tot;}LL calc2(int mid){ LL tot = 0; for (int i = 0;i < n;i++) if (a[i]>mid) tot += a[i] - mid; return tot;}int main(){ scanf ("%d%d", &n, &k); LL sum = 0LL; for (int i = 0;i < n;i++){ scanf("%d",&a[i]); sum += a[i]; } sort(a, a + n); int L = sum / n, R = (sum + n - 1) / n; int l = 0, r = L, ansL = 0, ansR = 0; while (l <= r){ int mid = (l + r) >> 1; if (calc1(mid) <= k) { ansL = mid; l = mid + 1; }else r = mid-1; } l = R;r = 1e9; while (l <= r){ int mid = (l + r) >> 1; if (calc2(mid) <= k) { ansR = mid; r =mid - 1; }else l = mid + 1; } printf("%d\n",ansR - ansL); return 0;}
G - Vasya and String (Codeforces 676C)
题目链接
【题意】
给你一个长度为n的只含a,b的字符串,最多改变其中的k个字符,求可以得到的最长的连续子序列。
【分析】
可以用二分或尺取法解决。
二分:
枚举起点,二分末点,判断这段的要替换的字符的数量是否小于等于k,这个字符数量用前缀和处理。
需要对替换a和替换b二分两遍。
尺取法:
同样需要两遍尺取,L,R为区间,
如果当前子序列L,R的需要替换的字符<=k就R++,否则L++使需要替换的字符
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;char s[100100];int main(){ int n,k; scanf("%d%d",&n,&k); scanf("%s",s); queue <char> Q; int maxn=0; int len=0; for (int i=0; i<n; i++) { if (s[i]=='a') Q.push(s[i]); else if (len<k) { len++; Q.push(s[i]); } else { maxn=max(maxn,(int)Q.size()); while (!Q.empty()&&Q.front()=='a') Q.pop(); if (!Q.empty()) { Q.pop(); Q.push(s[i]); } } } maxn=max(maxn,(int)Q.size()); while (!Q.empty()) Q.pop(); len=0; for (int i=0; i<n; i++) { if (s[i]=='b') Q.push(s[i]); else if (len<k) { len++; Q.push(s[i]); } else { maxn=max(maxn,(int)Q.size()); while (!Q.empty()&&Q.front()=='b') Q.pop(); if (!Q.empty()) { Q.pop(); Q.push(s[i]); } } } maxn=max(maxn,(int)Q.size()); printf("%d\n",maxn); return 0;
- sduacm2016级暑假集训 二分&尺取&三分
- sduacm2016级暑假集训 背包
- sduacm2016级暑假集训 搜索&并查集
- sduacm2016级暑假集训 最短路&最小生成树
- sduacm2016暑假集训周赛【一】
- 2014年暑假培训 - 二分三分
- 暑假集训--训练1 二分搜索
- 暑假集训日记--8.11--二分+单调队列
- 暑假集训
- 暑假集训
- 暑假集训
- 暑假集训
- CSU-ACM暑假集训训练1(二分 2015/7/21)
- 暑假集训-二分图,网络流,2-SAT
- CSU-ACM2016暑假集训训练1-二分搜索-C
- csu-acm2017暑假集训2-二分搜索D
- CSU-ACM2017暑假集训2-二分搜索 hdu2119
- CSU-ACM2017暑假集训2-二分搜索 F
- 【数据结构】循环链表与双向链表
- 进制转换
- MYSQL 逻辑架构
- JAVA与网络开发(TCP:Socket、ServerSocket;UDP:DatagramSocket、DatagramPacket;多线程的C/S通讯、RMI开发概述)
- webstorm 激活码、注册码
- sduacm2016级暑假集训 二分&尺取&三分
- 实现一个Add函数,让两个数相加,但是不能使用+、-、*、/等四则运算符。ps:也不能用++、--等等
- SignalR+HTML5实现消息推送及Android通知栏消息
- 20170715
- LVM逻辑卷管理
- VLC搭建UDP直播流,图文介绍
- Git学习笔记(1)----简介
- java--集合类型list、set、Map的用法和区别
- 接口 interface