最近状态不好,采用边写边记录的方式,看能否解决一下。
二分:
Hdu 2141 Can you find it?(easy) 点击打开链接
二分查找,给三个数列(a,b,c),从每个数列中各找一个,看能否和为X。
转化为a+b=X-c,将a+b的可能找出来,排序。(n^2+2*n^2*logn的时间复杂度)
二分查找等于X-c的。(n*logn的时间复杂度)由于n最大为500,所以时间复杂度还是可以。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int Len=503;
const int MLen=250003;
int x,L,N,M,a[Len],b[Len],c[Len],d[MLen],top;
bool Binary_search(int y){
int low=0,high=top;
while(high>=low){
int mid=(high+low)/2;
if(d[mid]==y) return true;
if(d[mid]>y) high=mid-1;
else low=mid+1;
}
return false;
}
int main(){
int k=1;
while(~scanf("%d%d%d",&L,&N,&M)){
for(int i=0;i<L;i++)
scanf("%d",&a[i]);
for(int i=0;i<N;i++)
scanf("%d",&b[i]);
for(int i=0;i<M;i++)
scanf("%d",&c[i]);
top=0;
for(int i=0;i<L;i++){
for(int j=0;j<N;j++)
d[top++]=a[i]+b[j];
}top--;
sort(d,d+top);
int s;
scanf("%d",&s);
printf("Case %d:\n",k++);
while(s--){
scanf("%d",&x);
bool flag=false;
for(int i=0;i<M;i++){
if(Binary_search(x-c[i])){
flag=true;
break;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
比较典型的二分查找吧。。!!
Hdu 2899 strange faction点击打开链接
Now, here is a fuction:
F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)
Can you find the minimum value when x is between 0 and 100.
简短的题目,直接贴这儿了。意思就是给一个y值,求x从0到100的最小值。
对其求导,等其斜率函数:F‘(x)=42*x^6+48*x^5+21*x^2+10*x-y;那么就是求其斜率函数为0的时候的值。(这个...不要解释了)
也就是求42*x^6+48*x^5+21*x^2+10*x=y,可知F‘(x)=42*x^6+48*x^5+21*x^2+10*x,是单调递增的,所以,该题可以二分法来求该方程的解。
Ps,函数中用二分法求解方程的解时,需要要求该函数是单调的。!!
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int Len=503;
const int MLen=250003;
int x,L,N,M,a[Len],b[Len],c[Len],d[MLen],top;
bool Binary_search(int y){
int low=0,high=top;
while(high>=low){
int mid=(high+low)/2;
if(d[mid]==y) return true;
if(d[mid]>y) high=mid-1;
else low=mid+1;
}
return false;
}
int main(){
int k=1;
while(~scanf("%d%d%d",&L,&N,&M)){
for(int i=0;i<L;i++)
scanf("%d",&a[i]);
for(int i=0;i<N;i++)
scanf("%d",&b[i]);
for(int i=0;i<M;i++)
scanf("%d",&c[i]);
top=0;
for(int i=0;i<L;i++){
for(int j=0;j<N;j++)
d[top++]=a[i]+b[j];
}top--;
sort(d,d+top);
int s;
scanf("%d",&s);
printf("Case %d:\n",k++);
while(s--){
scanf("%d",&x);
bool flag=false;
for(int i=0;i<M;i++){
if(Binary_search(x-c[i])){
flag=true;
break;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
典型的函数求解时,用到的二分求解。
Hdu 3400 Line belt 点击打开链接
因为是在做二分做题,好不容易理解了题意。
说是,给两条线段AB,CD,问从A到D的最短时间,因为在AB,CD上的速度和在其他地方的速度是不一样的,所以,可能是,在AB,CD上各走一部分的路程,列出一个关系式,一个两个未知数的方程,二分?不会啊。
百度一下思路:三分,真心不会。马上就学!!
Hdu 2289 Cup 点击打开链接
说是,给一个杯子(圆台),里面有水,让求水的高度。
擦,圆台体积,表面积神马的,忘的一塌糊涂啊。复习一下!!!
然后就是用水的高度来表示一下水面的半径!!
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double pi=3.1415926535898;
const double eps=1e-9;
double r,R,H,V;
double f(double h){
// return (pi*h*(r*r+((h*(R-r)+r*H)/H*(h*(R-r)+r*H)/H)+(h*(R-r)+r*H)/H*r))/3.0;
return (pi*h*(pow(r,2)+pow((h*(R-r)+r*H)/H,2)+(h*(R-r)+r*H)/H*r))/3.0;
}
double Binary_search(){
double low=0,high=H;
while(fabs(high-low)>eps){
double mid=(high+low)/2;
double tmp=f(mid);
// printf("%.9lf\n",)
if(tmp==V) return mid;
if(tmp>V) high=mid;
else low=mid;
}
return (high+low)/2;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%lf%lf%lf%lf",&r,&R,&H,&V);
printf("%.6lf\n",Binary_search());
}
return 0;
}
思路很是清晰,就是体积+面积神马的公式忘的一干二净了。记住啊!!
Hdu 2446 Shell Pyramid 点击打开链接
题意很简单(虽然题目很长),就是 1 2 3 4 5 ....每堆炮弹的数量,然后问你,编号为s的炮弹的Layer,Row,Cloumn。
比较麻烦的就是其数据范围比较大,2^63,大数据需要注意的小bug有很多。
该题用到的是打表二分查找。
一开始,我一直顾忌,得打多少?其实,应该仔细计算一下,s最大为2^63次方,?根据前n项和的通项公式就可以得到!!think more。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef unsigned __int64 LL;
const unsigned int N=3810776;
LL sum[N];
LL Binary_search(LL x){
LL low=0,high=N-1;
while(high>=low){
LL mid=(high+low)/2;
if(sum[mid]==x) return mid;
if(sum[mid]>x) high=mid-1;
else low=mid+1;
}
return low;
}
int main(){
sum[0]=0;sum[1]=1;
for(LL i=2;i<N;i++){
sum[i]=i*(i+1)*(i+2)/6;
}
LL n,T;
scanf("%I64u",&T);
while(T--){
scanf("%I64u",&n);
LL Layer=Binary_search(n);
LL tmp=n-(Layer*Layer*Layer-Layer)/6;
LL Row=(LL)sqrt(tmp*2);
if(Row*(Row+1)/2<tmp) Row++;
printf("%I64u %I64u %I64u\n",Layer,Row,tmp-Row*(Row-1)/2);
}
return 0;
}