2018暑假二分&&三分

Can you find it?

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/Others)
Total Submission(s): 41136    Accepted Submission(s): 10019

 

 

 

Problem Description

Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X.

 

 

Input

There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers.

 

 

Output

For each case, firstly you have to print the case number as the form "Case d:", then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print "YES", otherwise print "NO".

 

 

Sample Input


 

3 3 3 1 2 3 1 2 3 1 2 3 3 1 4 10

 

 

Sample Output


 

Case 1: NO YES NO

 

 

Author

wangye

 

 

Source

HDU 2007-11 Programming Contest

 

 

Recommend

威士忌

 题目大意是说在三个数列A、B、C中寻找是否有满足Ai+Bj+Ck = X.

把其中两个数组两两相加得到新数组,然后遍历另外一个,二分查找新的数组

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
const int maxn=555;
int a[maxn],b[maxn],c[maxn];
int d[maxn*maxn];
//set<int>s;
int n,m,o;
int k=0;
void fin(int x)
{
    for(int i=0;i<o;i++)
    {
        int t=x-c[i];
        int L=0,R=k-1;
        while(L<=R)
        {
            int mid=(L+R)/2;
            if(d[mid]==t)
            {
                printf("YES\n");
                return;
            }
            if(d[mid]>t)
            {
                R=mid-1;
            }
            else
            {
                L=mid+1;
            }
        }
    }
    printf("NO\n");
}
int main()
{
    int T=0;
    while(~scanf("%d%d%d",&m,&n,&o))
    {
        //s.clear();
        for(int i=0;i<m;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
            scanf("%d",&b[i]);
        for(int i=0;i<o;i++)
            scanf("%d",&c[i]);
        int q;
        scanf("%d",&q);
        k=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                int t=a[j]+b[i];
                d[k]=t;
                k++;
            }
        }
        sort(d,d+k);
        sort(c,c+o);
        printf("Case %d:\n",++T);
        while(q--)
        {
            int x;
            scanf("%d",&x);
            fin(x);
        }

    }
    return 0;
}

1023: 修路

Description

 

前段时间,某省发生干旱,B山区的居民缺乏生活用水,现在需要从A城市修一条通往B山区的路。假设有A城市通往B山区的路由m条连续的路段组成,现在将这m条路段承包给n个工程队(≤ ≤ 300)。为了修路的便利,每个工程队只能分配到连续的若干条路段(当然也可能只分配到一条路段或未分配到路段)。假设每个工程队修路的效率一样,即每修长度为1的路段所需的时间为1。现在给出路段的数量m,工程队的数量n,以及m条路段的长度(这m条路段的长度是按照从A城市往B山区的方向依次给出,每条路段的长度均小于1000),需要你计算出修完整条路所需的最短的时间(即耗时最长的工程队所用的时间)。

Input

 

第一行是测试样例的个数T ,接下来是T个测试样例,每个测试样例占2行,第一行是路段的数量m和工程队的数量n,第二行是m条路段的长度。

Output

 

对于每个测试样例,输出修完整条路所需的最短的时间。

Sample Input

2
4 3
100 200 300 400
9 4
250 100 150 400 550 200 50 700 300

Sample Output

400
900

Hint

Source

中南大学第四届大学生程序设计竞赛

 

二分完路的最短花费时间,遍历数组看mid时间内是否能完成

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
const int maxn=333;
int n,m;
int a[maxn];


int main()
{

    int T=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&n);
        a[0]=0;
        int maxx=0,sum=0;;
        for(int i=1;i<=m;i++)
        {
            int x;
            scanf("%d",&x);
            maxx=max(maxx,x);
            sum+=x;
            a[i]=x;
        }
        if(n>m)
            n=m;
        int L=maxx,R=sum;
        int ans=1000*300+1;
        while(L<=R)
        {
            int mid=(L+R)/2;
            int len=0;
            int N=0;
            int maxlen=0;
            for(int i=1;i<=m;i++)
            {
                if(len+a[i]>mid)
                {
                    maxlen=max(maxlen,len);
                    //printf("%d %d %d %d\n",i,len,maxlen,mid);
                    len=a[i];
                    N++;
                    continue;
                }
                len+=a[i];
            }
            N++;
            maxlen=max(maxlen,len);
            if(N<=n)
            {
                ans=min(ans,maxlen);
                R=mid-1;
            }
            else
            {
                L=mid+1;
            }


        }
        printf("%d\n",ans);
    }
    return 0;
}

Can you solve this equation?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 25051    Accepted Submission(s): 10781


 

Problem Description

Now,given the equation 8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,can you find its solution between 0 and 100;
Now please try your lucky.

 

 

Input

The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has a real number Y (fabs(Y) <= 1e10);

 

 

Output

For each test case, you should just output one real number(accurate up to 4 decimal places),which is the solution of the equation,or “No solution!”,if there is no solution for the equation between 0 and 100.

 

 

Sample Input


 

2 100 -4

 

 

Sample Output


 

1.6152 No solution!

 

 

Author

Redow

 

 

Recommend

lcy

 

寻找满足8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y的x([0,100])

浮点数二分,直接套模板

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#define eps 0.00000001
using namespace std;
const int maxn=333;
double fun(double x)
{
    return 8*x*x*x*x + 7*x*x*x + 2*x*x + 3*x + 6;
}


int main()
{

    int T=0;
    scanf("%d",&T);
    double ans=-1;
    while(T--)
    {
        double y;
        scanf("%lf",&y);
        if(y<fun(0)||y>fun(100))
        {
            printf("No solution!\n");
            continue;
        }

        double L=0,R=100,mid;
       
        while(R-L>eps)
        {
            mid=(L+R)/2;
            double tem=fun(mid);
            
            if(tem<y)
            {
                L=mid;
            }
            else
            {
                R=mid;
            }
        }

            printf("%.4lf\n",mid);


    }
    return 0;
}

1976: 搬运工小明

Description

作为老人的小明非常忧伤,因为他马上要被流放到本部去了,住进全左家垅最有历史感的11舍真是一件非常荣幸的事情。
搬行李是个体力活,小明发现自己的行李太多啦,所以他决定去买很多个袋子来装走。到了超市的小明发现,不同大小的袋子居然价格一样???虽然买最大的自然最赚,但是小明是名远近闻名的环保人士,他觉得袋子只要能装下他的行李就够了,并且为了不麻烦收银的小姐姐(⊙o⊙)…,他也只会购买同一种大小的袋子。因此他希望在能装下所有行李的前提下,袋子越小越好。同时为了避免弄乱行李,小明希望同一个袋子装的是位置连续相邻的行李。
小明摸了摸口袋发现自己带的钱最多能买N个袋子,数学特别差的他不知道到底该买多大的才合适,所以想靠你来解决这个问题了。

Input

第一行为一个数字T(T<=10)表示数据组数
第二行为两个数字N(N <= 10^5)和 M(M <= 10^5)表示袋子个数和小明的行李个数
第三行为M个数字,第i个数字a[i]表示小明的第i个行李体积为a[i](0<a[i] <= 10^9)

Output

输出一行表示袋子的最小体积(整数)

Sample Input

1
3 3
1 1 1

Sample Output

1

Hint

袋子不能装下体积大于其容积的物品
多个物品满足体积之和小于等于一个袋子的容积,就能被装进

Source

2017年8月月赛

Author

卢铭威

 

和修路那题思路一样,就是数据变大了,改成long long就可以了

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
typedef long long LL;
using namespace std;
const int maxn=100000+11;
int n,m;
LL a[maxn];


int main()
{

    int T=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        a[0]=0;
        LL maxx=0,sum=0;;
        for(int i=1;i<=m;i++)
        {
            LL x;
            scanf("%lld",&x);
            maxx=max(maxx,x);
            sum+=x;
            a[i]=x;
        }
        if(n>m)
            n=m;
        LL L=maxx,R=sum;
        LL ans=maxn*1e9;
        while(L<=R)
        {
            LL mid=(L+R)/2;
            LL len=0;
            int N=0;
            LL maxlen=0;
            for(int i=1;i<=m;i++)
            {
                if(len+a[i]>mid)
                {
                    maxlen=max(maxlen,len);
                    //printf("%d %d %d %d\n",i,len,maxlen,mid);
                    len=a[i];
                    N++;
                    continue;
                }
                len+=a[i];
            }
            N++;
            maxlen=max(maxlen,len);
            if(N<=n)
            {
                ans=min(ans,maxlen);
                R=mid-1;
            }
            else
            {
                L=mid+1;
            }


        }
        printf("%lld\n",ans);
    }
    return 0;
}

2112: Wells的明星生活

Description

和很多人想的不同,Wells其实是很低调的。

刚刚过了520和521,爱信不信,巨怂Wells和喜欢的小姐姐表白了!

Wells那是相当相当低调——之后的约会也是。不过,这次Wells遇到麻烦了……

Wells和小姐姐正在浪漫的约会呢,Wells猛然得到最新消息,有若干狗仔团队正闻讯蜂拥而来(Wells毕竟还是蛮很有名气的嘛)……

Wells真是不理解现在这些人对八卦的渴望怎么那么大,连保密工作做的这么好的Wells都未能幸免,这真是……

算了,别扯了,先溜吧,被狗仔队逮到可不好。

但是,Wells最近心情真的不好,厌睡厌食还厌学,难得和小姐姐的浪漫约会真不想撤,那么就能呆多久呆多久吧,Wells希望在不会被抓的前提下和小姐姐呆尽量久的时间。

城市可以看做是N行N列的方格,每一个格子会是一个建筑物,一片空地,一个狗仔队的窝点,或者是Wells的家。我们认为两个格子如果有相同的边,那么就是相邻的。城市里居民都是良民,每次走的时候,只会走相邻的格子。显然的,在私闯民宅可不好,所以不论是谁都不会闯到建筑物里的……

由于要保护小姐姐, Wells每一秒至多走S步,S可能很大,因为这是爱情的力量!

当Wells得知狗仔队将至的消息时,Wells在和小姐姐约会,而狗仔队都在各自窝点。随着时间的前进,每一秒都会按照如下的顺序发生着一些事件:

  • 如果Wells还在约会地点,那么他可以选择现在这一秒是和小姐姐浪漫,还是开始逃跑——如果是继续浪漫,那么这一秒Wells是不会移动的,如果逃跑,那么接下来Wells可以在城市里移动不超过S步——当然的,开始逃跑了怎么还会有心思浪漫呢?所以一旦离开了,Wells就会保护着小姐姐一直不停的逃跑。当然了,如果在某个位置遇到了狗仔队,那么可怜的Wells就要悲剧了…

  • 当Wells决定或者移动完毕之后,所有的狗仔队会向四周更远的格子移动一步——当然,也只会走到空地上,并且最邪恶的是一旦狗仔队走到了一个格子,就会派一个狗仔留守在那里——或者可以这么说,如果格子a和b是相邻的空地,并且在前一秒狗仔队占据了格子a,那么这一秒过后,a和b都将被狗仔队占据。最开始的时候,狗仔队占据了所有狗仔窝点所在的格子。

狗仔和Wells都不能走出城市。并且,显然的,根据规则,Wells继续和小姐姐浪漫的时间,必然是一个整数秒。

狗仔队是无法占领Wells的家的,所以Wells只要回到家里就安全啦!

现在Wells想知道如果要能够安全带着小姐姐回到家,那么最多他还能和小姐姐浪漫多长时间呢?

Input

第一行两个整数,N,S ,1≤N≤800 1≤S≤1000

接下来N行每行N个字符描述每个格子的具体情况

T 这个格子是一个建筑物

G 这是一块空地

M 这是Wells和小姐姐浪漫的地方,当然也是个空地

D 这是Wells的家

H 这是一个狗仔队的窝点

Output

一行一个整数,表示Wells最多还能和小姐姐浪漫多长时间,如果Wells不可能回到家了,那么就输出-1,否则显然答案是非负整数。

约定:

地图中有且仅有一个M,一个D,并且至少有一个H。

同样的,保证一定存在一条路能够从M走到D(否则Wells是怎么去和小姐姐约会的呢?)

保证答案不为无限大

Sample Input

7 3 
TTTTTTT 
TGGGGGT 
TGGGGGT 
MGGGGGD 
TGGGGGT 
TGGGGGT 
TGHHGGT 

Sample Output

2 

Hint

对于样例,一种可行的方法是,停留两秒,然后第一秒走三步到(3,3)第二秒走三步到(3,6),第三秒走两步到(4,7)中途不会遇到狗仔队 左上角格子为(1,1)

Source

Author

Wells

 

 

二分+bfs,先bfs求狗仔到达个空地的时间,然后二分停留时间,再bfs看停留mid是否能安全到家

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#define eps 0.00000001
using namespace std;
const int maxn=888;
int N,S;
char ma[maxn][maxn];//地图
int vis[maxn][maxn];//狗仔什么时候可以走到,墙为0,家为-1
int vist[maxn][maxn];//wells是否走过,走过为0
struct node
{
    int x,y;
    int step;
};
queue<node>gz;
node st,en;
int f[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int flag,mid;
int L=0,R=N*N;
bool OK(int x,int y)//越界,墙
{
    if(x>=0&&y>=0&&x<N&&y<N&&ma[x][y]!='T')
        return 1;
    return 0;
}
void init()//处理vis
{
    R=0;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            node tem;
            tem.x=i;
            tem.y=j;
            tem.step=0;
            if(ma[i][j]=='H')
            {
                vis[i][j]=0;
                gz.push(tem);
            }
            if(ma[i][j]=='M')
                st=tem;
            if(ma[i][j]=='D')
                en=tem;
            if(ma[i][j]=='T')
                vis[i][j]=0;
        }
    }
    while(!gz.empty())
    {
        node tem;
        tem=gz.front();
        gz.pop();
        R=max(R,tem.step);
        for(int i=0;i<4;i++)
        {
            int xx=tem.x+f[i][0];
            int yy=tem.y+f[i][1];

            if(OK(xx,yy)&&ma[xx][yy]!='D'&&vis[xx][yy]==-1)//其实约会的那块空地也可以不入队
            {
                vis[xx][yy]=tem.step+1;
                node t;
                t.x=xx;
                t.y=yy;
                t.step=tem.step+1;
                gz.push(t);
            }
        }
    }
}
queue<node>q;
void BFS()
{
    q.push(st);
    while(!q.empty())
    {
        node t=q.front();
        q.pop();
        if(t.x==en.x&&t.y==en.y)
        {
            flag=1;
            return;
        }
        for(int i=0;i<4;i++)
        {
            int xx=t.x+f[i][0];
            int yy=t.y+f[i][1];
            int time=(t.step+1)/S;

            if(OK(xx,yy)&&(time+mid<vis[xx][yy]||vis[xx][yy]==-1)&&vist[xx][yy])
            {
                vist[xx][yy]=0;

                node tem;
                tem.x=xx;
                tem.y=yy;
                tem.step=t.step+1;
                q.push(tem);
            }
        }

    }
}

int main()
{
    while(~scanf("%d%d",&N,&S))
    {
        memset(vis,-1,sizeof(vis));
        memset(vist,1,sizeof(vist));
        //printf("%d %d %d\n",vis[0][1],vis[22][0],vis[44][7]);
        for(int i=0;i<N;i++)
        {
            scanf("%s",ma[i]);
        }
        init();
        vist[st.x][st.y]=0;
        L=0;
        int ans=-1;
        while(L<=R)
        {
            flag=0;
            mid=(L+R)/2;
            BFS();
            if(flag)
            {
                ans=mid;
                L=mid+1;
            }
            else
                R=mid-1;
            memset(vist,1,sizeof(vist));
            while(!q.empty())
                q.pop();
        }
        printf("%d\n",ans);
    }
    return 0;
}

Strange fuction

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9540    Accepted Submission(s): 6493


 

Problem Description

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.

 

 

Input

The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has only one real numbers Y.(0 < Y <1e10)

 

 

Output

Just the minimum value (accurate up to 4 decimal places),when x is between 0 and 100.

 

 

Sample Input


 

2 100 200

 

 

Sample Output


 

-74.4291 -178.8534

 

 

Author

Redow

 

 

Recommend

lcy

 题意:求函数的最小值

三分例题,直接套模板

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#define eps 0.00000001
using namespace std;
const int maxn=333;
double fun(double x,double y)
{
    return 6 * x*x*x*x*x*x*x +8*x*x*x*x*x*x + 7*x*x*x + 5*x*x - y*x;
}


int main()
{

    int T=0;
    scanf("%d",&T);
    double ans=-1;
    while(T--)
    {
        double y;
        scanf("%lf",&y);

        double L=0,R=100,midl,midr;

        while(R-L>eps)
        {
            midl=(L+R)/2;
            midr=(midl+R)/2;

            double teml=fun(midl,y);
            double temr=fun(midr,y);
            if(teml<temr)
            {
                R=midr;
            }
            else
            {
                L=midl;
            }
        }

            printf("%.4lf\n",fun(midl,y));


    }
    return 0;
}

C. GukiZ hates Boxes

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Professor GukiZ is concerned about making his way to school, because massive piles of boxes are blocking his way.

In total there are n piles of boxes, arranged in a line, from left to right, i-th pile (1 ≤ i ≤ n) containing ai boxes. Luckily, m students are willing to help GukiZ by removing all the boxes from his way. Students are working simultaneously. At time 0, all students are located left of the first pile. It takes one second for every student to move from this position to the first pile, and after that, every student must start performing sequence of two possible operations, each taking one second to complete. Possible operations are:

  1. If i ≠ n, move from pile i to pile i + 1;
  2. If pile located at the position of student is not empty, remove one box from it.

GukiZ's students aren't smart at all, so they need you to tell them how to remove boxes before professor comes (he is very impatient man, and doesn't want to wait). They ask you to calculate minumum time t in seconds for which they can remove all the boxes from GukiZ's way. Note that students can be positioned in any manner after t seconds, but all the boxes must be removed.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 105), the number of piles of boxes and the number of GukiZ's students.

The second line contains n integers a1, a2, ... an (0 ≤ ai ≤ 109) where ai represents the number of boxes on i-th pile. It's guaranteed that at least one pile of is non-empty.

Output

In a single line, print one number, minimum time needed to remove all the boxes in seconds.

Examples

input

2 1
1 1

output

4

input

3 2
1 0 2

output

5

input

4 100
3 4 5 4

output

5

Note

First sample: Student will first move to the first pile (1 second), then remove box from first pile (1 second), then move to the second pile (1second) and finally remove the box from second pile (1 second).

Second sample: One of optimal solutions is to send one student to remove a box from the first pile and a box from the third pile, and send another student to remove a box from the third pile. Overall, 5 seconds.

Third sample: With a lot of available students, send three of them to remove boxes from the first pile, four of them to remove boxes from the second pile, five of them to remove boxes from the third pile, and four of them to remove boxes from the fourth pile. Process will be over in 5 seconds, when removing the boxes from the last pile is finished.

题目大意: n堆盒子,m个人,人到达第一堆盒子要1s,然后有两种操作:1.拿起一个盒子,花费1s;2.去第二堆,花费1

s。.........问怎样可以把盒子全部拿走(人最后在哪都可以,不要求到达终点)

二分总耗时,判断在mid内是否可以拿可以先假设只有一个人,然后遍历,判断当前人数是否能在mid内拿完a[0]~a[i],不能就增加人数,每增加一个人就可以分担mid-(i+1)个盒子,也就是当前所花时间use可改为use-(mid-(i+1))

#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
typedef long long LL;
#define eps 0.00000001
using namespace std;
const int maxn=100000+11;
LL a[maxn];
int main()
{
    int N,M;
    while(~scanf("%d%d",&N,&M))
    {
        LL sum=0;
        int n=0;
        for(int i=0;i<N;i++)
        {
            scanf("%lld",&a[i]);
            sum+=a[i];
            if(a[i]!=0)
                n=i;
        }
        n++;

        LL L=n,R=sum+n;
        LL ans=sum+n;

        while(L<=R)
        {
            LL mid=(L+R)/2;
            LL use=0;
            int m=M;
            for(int i=0;i<n;i++)
            {
                use+=a[i];
                while(use+i+1>=mid)
                {
                    use = use-(mid-i-1);
                    m--;
                    if(m<0)break;
                }
                if(m<0)break;
            }
            if(m<0||(m==0&&use>0))
            {
                L=mid+1;
            }
            else
            {
                ans=mid;
                R=mid-1;
            }

        }
        printf("%lld\n",ans);

    }
    return 0;
}

 

posted on 2018-07-25 09:39  一零七  阅读(210)  评论(0编辑  收藏  举报

导航