2018-07-25 训练1

  • A  -- Tricky Sum

  • Description

In this problem you are to calculate the sum of all integers from 1 to n, but you should take all powers of two with minus in the sum.

For example, for n = 4 the sum is equal to  - 1 - 2 + 3 - 4 =  - 4, because 1, 2 and 4 are 20, 21 and 22 respectively.

Calculate the answer for t values of n.

  • Input

The first line of the input contains a single integer t (1 ≤ t ≤ 100) — the number of values of n to be processed.

Each of next t lines contains a single integer n (1 ≤ n ≤ 109).

  • Output

Print the requested sum for each of t integers n given in the input.

  • Sample Input

2
4
1000000000

  • Sample Output

-4
499999998352516354

  • 题目理解

创建2的指数的数组,初始化指数和,可以直接使用upper_bound搜索到下一个位置然后对1-n的和减去2*相应2的指数的和.1-n使用公式x*(x+1)/2计算

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll pow2[32],sum2[32];
void init_pow2(){
   pow2[0]=1;sum2[0]=1;
   for(int i=1;i<32;++i){
      pow2[i]=pow2[i-1]*2;
   }
   for(int i=1;i<32;++i){
      sum2[i]=sum2[i-1]+pow2[i];
   }
   //printf("!!%lld %lld\n",pow2[31],sum2[31]);
   return ;
}
ll cal(ll x){
   if(x%2)
    return (x+1)/2*x;
   else
    return x/2*(x+1);
}
int main()
{
    int t;
    ll x,ans;
    init_pow2();
    while(scanf("%d",&t)!=EOF){
       while(t--){
          scanf("%lld",&x);
          int lct=upper_bound(pow2,pow2+32,x)-pow2;
          ans=cal(x)-2*sum2[lct-1];
          printf("%lld\n",ans);
       }
    }
    return 0;
}
  • B  -- Queries about less or equal elements

  • Description

You are given two arrays of integers a and b. For each element of the second array bj you should find the number of elements in array a that are less than or equal to the value bj.

  • Input

The first line contains two integers n, m (1 ≤ n, m ≤ 2·105) — the sizes of arrays a and b.

The second line contains n integers — the elements of array a ( - 109 ≤ ai ≤ 109).

The third line contains m integers — the elements of array b ( - 109 ≤ bj ≤ 109).

  • Output

Print m integers, separated by spaces: the j-th of which is equal to the number of such elements in array a that are less than or equal to the value bj.

  • Sample Input

5 4
1 3 5 7 9
6 4 2 8 


 5 5
1 2 1 2 5
3 1 4 1 5

  • Sample Output 

3 2 1 4 


 4 2 4 2 5

  • 题目理解

先对a数组进行排序然后遍历每个b数组元素使用upper_bound得到的下标就是前面小于或等于b[i]的个数

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=200005;
int a[maxn],b[maxn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i) scanf("%d",&a[i]);
    for(int i=0;i<m;++i) scanf("%d",&b[i]);
    sort(a,a+n);
    for(int i=0;i<m;++i){
        int ans=upper_bound(a,a+n,b[i])-a;
        if(i) printf(" ");
        printf("%d",ans);
    }
    printf("\n");
    return 0;
}
  • C  -- Nearest vectors

  • Description

You are given the set of vectors on the plane, each of them starting at the origin. Your task is to find a pair of vectors with the minimal non-oriented angle between them.

Non-oriented angle is non-negative value, minimal between clockwise and counterclockwise direction angles. Non-oriented angle is always between 0 and π. For example, opposite directions vectors have angle equals to π.

  • Input

First line of the input contains a single integer n (2 ≤ n ≤ 100 000) — the number of vectors.

The i-th of the following n lines contains two integers xi and yi (|x|, |y| ≤ 10 000, x2 + y2 > 0) — the coordinates of the i-th vector. Vectors are numbered from 1 to n in order of appearing in the input. It is guaranteed that no two vectors in the input share the same direction (but they still can have opposite directions).

  • Output

Print two integer numbers a and b (a ≠ b) — a pair of indices of vectors with the minimal non-oriented angle. You can print the numbers in any order. If there are many possible answers, print any.

  • Sample Input

4
-1 0
0 -1
1 0
1 1


6
-1 0
0 -1
1 0
1 1
-4 -5
-4 -6

  • Sample Output

3 4


6 5

  • 题目理解

atan2函数求出弧度,然后自定义结构体将每个边的弧度存在数组里面,自己写cmp函数使用sort排序得到相邻的两条边(最小角只会出现在相邻两条边中毫无疑问),这里就是要注意最后一条边和第一条边的角度也要算进来比较。PI的精度取3.141592会WA。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#define PI 3.14159265358979
using namespace std;
typedef long double ld;
const int maxn=100005;
struct node{
   ld atan;
   int id;
} ;
bool cmp(node& a,node& b){
   return a.atan<b.atan;
}
node vectors[maxn];
int main()
{
    ld x,y;
    int n;
    cin >> n;
    for(int i=1;i<=n;++i){
        cin >> x >> y;
        ld ans=atan2(y,x);
        vectors[i-1].atan=ans;
        vectors[i-1].id=i;
    }
    sort(vectors,vectors+n,cmp);
    ld mini=4;
    int ans1,ans2;
    //for(int i=0;i<n;++i){
     //    cout << vectors[i].id << " " << vectors[i].atan << endl;
    //}
    for(int i=1;i<n;++i){
        ld res=vectors[i].atan-vectors[i-1].atan;
        if(res<mini){
            ans1=vectors[i].id,ans2=vectors[i-1].id;
            mini=res;
        }
    }
    ld res=(vectors[0].atan-vectors[n-1].atan)+2*PI;
    if(res<mini){
            ans1=vectors[0].id,ans2=vectors[n-1].id;
            mini=res;
    }
    cout << ans1 << " " << ans2 << endl;
    return 0;
}
  • D  -- Can you find it?

  • Description

  • Input

The input consists of several tests case with the following format.

d n b

p1 h1

p2 h2

pn hn

For each test, the first line contains three integers, d, n, and b. Here, d is the distance from the launcher to the target spot (1 ≤ d ≤ 10000), n is the number of obstacles (1 ≤ n ≤ 10), and b is the maximum number of bounces allowed, not including the bounce at the target spot (0 ≤ b ≤ 15).

Each of the following n lines has two integers. In the k-th line, pk is the position of the k-th obstacle, its distance from the launcher, and hk is its height from the ground level. You can assume that 0 < p1, pk < pk + 1 for k = 1, …, n − 1, and pn < d. You can also assume that 1 ≤ hk ≤ 10000 for k = 1, …, n.

  • Output

Output the smallest possible initial speed vi that makes the bullet reach the target. The initial speed vi of the bullet is defined as follows.

v_{i}=\sqrt{v_{ix}^{2}+v_{iy}^{2}}

The output should not contain an error greater than 0.0001.

  • Sample Input

100 1 0

50 100


10 1 0

4 2


100 4 3

20 10

30 10

40 10

50 10


343 3 2

56 42

190 27

286 34

  • Sample Output

14.57738

3.16228

7.78175

11.08710

  • 题目理解

首先可以通过开口len长度和最高点坐标将最高长度解出来,然后得到合速度与高度h的关系式从而解出最小值。可以直接进行也可以用三分逼近求出最小速度

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cfloat>
using namespace std;
const int maxn=10010;
const double eps=1e-6;
int x[15],y[15];
int main()
{
    double d,tx,ty;
    int n,b;
    while(cin >> d >> n >> b){
        for(int i=0;i<n;++i)
            cin >> x[i] >> y[i];
        double ans=DBL_MAX;
        for(int i=1;i<=b+1;++i){
            double len=d/i;
            bool flag=false;
            double maxy=0;
            for(int j=0;j<n;++j){
                tx=x[j],ty=y[j];
                while(tx>=len){
                    tx-=len;
                }
                if(fabs(tx)<=eps){
                    flag=true;
                    break;
                }
                double tmaxy=len*len*ty/(len-tx)/tx/4;
                maxy=maxy>tmaxy?maxy:tmaxy;
            }
            if(flag) continue;
            if(maxy<len/4+eps) ans=len<ans?len:ans;
            else{
                double tmp=len*len/8/maxy+2*maxy;
                ans=tmp<ans?tmp:ans;
            }
        }
        printf("%.5lf\n",sqrt(ans));
    }
    return 0;
}
  • E  -- Maifia

  • Description

One day n friends gathered together to play "Mafia". During each round of the game some player must be the supervisor and other n - 1 people take part in the game. For each person we know in how many rounds he wants to be a player, not the supervisor: the i-th person wants to play ai rounds. What is the minimum number of rounds of the "Mafia" game they need to play to let each person play at least as many rounds as they want?

  • Input

The first line contains integer n (3 ≤ n ≤ 105). The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 109) — the i-th number in the list is the number of rounds the i-th person wants to play.

  • Output

In a single line print a single integer — the minimum number of game rounds the friends need to let the i-th person play at least ai rounds.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

  • Sample Input

3
3 2 2

  • Sample Output

4

  • 题目理解

求最小的最大可以用二分做判断mid是否成立然后缩小区间;也可以推导公式(ans-a[1])+(ans-a[2])+...+(ans-a[n])\geq ans移项得到ans\geq \frac{a[1]+a[2]+...+a[n]}{n-1}最后答案向上取整即可但是需要注意的是ans最后一定要大于等于任意a[i]否则WA

推导代码:


//推导代码

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll a[maxn];
int n;
int main()
{
    ll ans=0,big=0;
    cin >> n;
    a[0]=0;
    for(int i=1;i<=n;++i){
        cin >> a[i];
        if(a[i]>big)
            big=a[i];
        a[i]+=a[i-1];
    }
    ans=a[n]/(n-1);
    if(a[n]%(n-1))
        ans++;
    if(ans<big)
        ans=big;
    cout << ans <<endl;
    return 0;
}

二分代码

//二分代码

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll a[maxn];
int n;
bool check_ok(ll ans){
   ll cnt=ans;
   for(int i=0;i<n;++i)
     cnt-=(ans-a[i]);
   return cnt<=0;
}
int main()
{
    ll ans=0,l=-1;
    cin >> n;
    for(int i=0;i<n;++i){
        cin >> a[i];
        ans+=a[i];
        if(a[i]>l)
            l=a[i];
    }
    ll mid=0;
    while(l<ans){
        mid=(l+ans)/2;
        //cout << l << " " << ans <<" " << mid << endl;
        if(check_ok(mid))
            ans=mid;
        else
            l=mid+1;;
    }
    cout << ans <<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zm_zsy/article/details/81207282