2014年 acmicpc北京区域赛题目(hdu5112 hdu5119 hdu5120 hdu5122)

A Curious Matt

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 1071    Accepted Submission(s): 564


Problem Description
There is a curious man called Matt.

One day, Matt's best friend Ted is wandering on the non-negative half of the number line. Matt finds it interesting to know the maximal speed Ted may reach. In order to do so, Matt takes records of Ted’s position. Now Matt has a great deal of records. Please help him to find out the maximal speed Ted may reach, assuming Ted moves with a constant speed between two consecutive records.
 

Input
The first line contains only one integer T, which indicates the number of test cases.

For each test case, the first line contains an integer N (2 ≤ N ≤ 10000),indicating the number of records.

Each of the following N lines contains two integers t i and x i (0 ≤ t i, x i ≤ 10 6), indicating the time when this record is taken and Ted’s corresponding position. Note that records may be unsorted by time. It’s guaranteed that all t i would be distinct.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1), and y is the maximal speed Ted may reach. The result should be rounded to two decimal places.
 

Sample Input
  
  
2 3 2 2 1 1 3 4 3 0 3 1 5 2 0
 

Sample Output
  
  
Case #1: 2.00 Case #2: 5.00
Hint
In the first sample, Ted moves from 2 to 4 in 1 time unit. The speed 2/1 is maximal. In the second sample, Ted moves from 5 to 0 in 1 time unit. The speed 5/1 is maximal.


解题思路:

结构体排序题,没什么好说的。


AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn = 10005;
const double inf = 0x3f3f3f3f;

struct point
{
    int t;
    int x;    
}pai[maxn];

double max(double a,double b)
{
    return a > b ? a : b;    
}

bool cmp(struct point a,struct point b)
{
    if(a.x == b.x) return a.x < b.x;
    return a.t < b.t;
}

int main()
{
    int T;
    int m;
    int i;
    int cnt = 0;
    //freopen("1.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&pai[i].t,&pai[i].x);
        }
        sort(pai,pai+m,cmp);
        double Max = -inf;
        double t1,x1;
        for(i=1;i<m;i++)
        {
            t1 = abs(pai[i].t - pai[i-1].t);
            x1 = abs(pai[i].x - pai[i-1].x);
            if(x1 * 1.0 / t1 > Max)
            {
                Max = x1 / t1;
            }
        }
        printf("Case #%d: %.2f\n",++cnt,Max);
    }
    return 0;    
}


Happy Matt Friends

Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Others)
Total Submission(s): 1303    Accepted Submission(s): 504


Problem Description
Matt has N friends. They are playing a game together.

Each of Matt’s friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends’magic numbers is no less than M , Matt wins.

Matt wants to know the number of ways to win.
 

Input
The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains two integers N, M (1 ≤ N ≤ 40, 0 ≤ M ≤ 10 6).

In the second line, there are N integers ki (0 ≤ k i ≤ 10 6), indicating the i-th friend’s magic number.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y indicates the number of ways where Matt can win.
 

Sample Input
  
  
2 3 2 1 2 3 3 3 1 2 3
 

Sample Output
  
  
Case #1: 4 Case #2: 2
Hint
In the first sample, Matt can win by selecting: friend with number 1 and friend with number 2. The xor sum is 3. friend with number 1 and friend with number 3. The xor sum is 2. friend with number 2. The xor sum is 2. friend with number 3. The xor sum is 3. Hence, the answer is 4.
 

Source


题目大意:

求给定几个数中选取数相异或结果大于或等于给定的一个数的组合有多少种?


解题思路:

我们让dp[i][j]表示第i个元素和当前异或的值j,整个二维数组表示个数,因为j可能很大,所以i必须使用滚动数组才可以,可以让数组降到2 * 2 ^ 20 ~ 2 * 2 ^ 21这个范围内,不然数组开不了那么大,然后很容易知道dp[i][j]为前第i-1个状态取或不取的结果的个数之和,容易写出方程dp[i][j] = dp[i-1][j] + dp[i-1][j ^ num[i]],其中j为从0遍历到2 ^ 21,以便等下处理。预处理完之后累加dp[i][m....2^21]的和,即是最后的结果。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = (1<<21);

typedef long long ll;

int num[45];
ll dp[2][maxn];

int main()
{
    int T;
    int m,n;
    int i,j;
    int cnt = 0;
    //freopen("1.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&n);
        for(i=1;i<=m;i++)
        {
            scanf("%d",&num[i]);
        }
        memset(dp,0,sizeof(dp));
        dp[0][0] = 1;
        ll ans;
        for(i=1;i<=m;i++)
        {
            for(j=0;j<maxn;j++)
            {    
                dp[i%2][j] = dp[(i-1)%2][j]+dp[(i-1)%2][j^num[i]];
            }
        }
        ans = 0;
        for(j=n;j<maxn;j++)
        {
            ans += dp[m % 2][j];
        }
        printf("Case #%d: %lld\n",++cnt,ans);
    }
    return 0;
}

Intersection

Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 1168    Accepted Submission(s): 450


Problem Description
Matt is a big fan of logo design. Recently he falls in love with logo made up by rings. The following figures are some famous examples you may know.


A ring is a 2-D figure bounded by two circles sharing the common center. The radius for these circles are denoted by r and R (r < R). For more details, refer to the gray part in the illustration below.


Matt just designed a new logo consisting of two rings with the same size in the 2-D plane. For his interests, Matt would like to know the area of the intersection of these two rings.
 

Input
The first line contains only one integer T (T ≤ 10 5), which indicates the number of test cases. For each test case, the first line contains two integers r, R (0 ≤ r < R ≤ 10).

Each of the following two lines contains two integers x i, y i (0 ≤ x i, y i ≤ 20) indicating the coordinates of the center of each ring.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the area of intersection rounded to 6 decimal places.
 

Sample Input
   
   
2 2 3 0 0 0 0 2 3 0 0 5 0
 

Sample Output
   
   
Case #1: 15.707963 Case #2: 2.250778
 

Source


题目大意:

给定两个2D的圆环,求相交的面积.


解题思路:

画个图,可以用容斥定律推出公式,两个圆环相交的面积 = 两个大圆相交的面积 - 2 * 大圆和小圆相交的面积 + 两个小圆相交的面积 (因为多给人家减了一次所以要补回来),模版是圆和圆相交面积的模版,注意精度问题,1A.


AC代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;

const double PI = acos(-1.0);

double Deg2Rad(double deg)
{
    return (deg * PI / 180.0);
}

double Rad2Deg(double rad)
{
    return (rad * 180.0 / PI);
}

double ArcSin(double val) {
    return Rad2Deg(asin(val));
}

double ArcCos(double val)
{
    return Rad2Deg(acos(val));
}

double Sin(double deg)
{
    return sin(Deg2Rad(deg));
}
struct CIRCLE
{
    double x;
    double y;
    double r;
    CIRCLE() {}
    CIRCLE(double x1,double y1,double r1):x(x1),y(y1),r(r1) {}
};

struct POINT
{
    double x;
    double y;
    POINT() : x(0),y(0) {};
    POINT(double x1,double y1) : x(x1),y(y1) {};
};

POINT Center(const CIRCLE &circle)
{
    return POINT(circle.x,circle.y);
}

double Area(const CIRCLE &circle)
{
    return PI * circle.r * circle.r;
}

double Distance(const POINT &a,const POINT &b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));    
}

double CommonArea(const CIRCLE &A,const CIRCLE &B)
{
    double area = 0.0;
    const CIRCLE &M = (A.r > B.r) ? A : B;
    const CIRCLE &N = (A.r > B.r) ? B : A;
    double D = Distance(Center(M),Center(N));    
    if((D < M.r + N.r) && (D > M.r - N.r))
    {
        double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D);
        double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D);
        double alpha = 2.0 * ArcCos(cosM);
        double beta = 2.0 * ArcCos(cosN);
        double TM = 0.5 * M.r * M.r * Sin(alpha);
        double TN = 0.5 * N.r * N.r * Sin(beta);
        double FM = (alpha / 360.0) * Area(M);
        double FN = (beta / 360.0) * Area(N);
        area = FM + FN - TM - TN;
    }
    else if(D <= M.r - N.r)
    {
        area = Area(N);    
    } 
    return area;
}

int main()
{
    int T;
    int R,r;
    int Rx1,Ry1;
    int rx1,ry1;
    int cnt = 1;
    //freopen("1.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        CIRCLE c1,c2; //两个小圆
        CIRCLE C1,C2; //两个大圆
        scanf("%d%d",&r,&R); //内圆环半径,外圆环半径 
        scanf("%d%d",&Rx1,&Ry1); //第一个圆心坐标 
        scanf("%d%d",&rx1,&ry1); //第二个圆心坐标
        c1.r = r;
        c2.r = r;
        C1.r = R; 
        C2.r = R;
        c1.x = Rx1; //第一个小圆r
        c1.y = Ry1;
        C1.x = Rx1; //第一个大圆R
        C1.y = Ry1;
        c2.x = rx1; //第二个小圆r
        c2.y = ry1;
        C2.x = rx1; //第二个大圆R
        C2.y = ry1;
        double res1 = CommonArea(C1,C2);
        double res2 = CommonArea(c1,C2) + CommonArea(C1,c2);
        double res3 = CommonArea(c1,c2);
        double finres = res1 - res2 + res3;
        printf("Case #%d: %.6f\n",cnt++,finres);
    }
    return 0;
}


K.Bro Sorting

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 1148    Accepted Submission(s): 518


Problem Description
Matt’s friend K.Bro is an ACMer.

Yesterday, K.Bro learnt an algorithm: Bubble sort. Bubble sort will compare each pair of adjacent items and swap them if they are in the wrong order. The process repeats until no swap is needed.

Today, K.Bro comes up with a new algorithm and names it K.Bro Sorting.

There are many rounds in K.Bro Sorting. For each round, K.Bro chooses a number, and keeps swapping it with its next number while the next number is less than it. For example, if the sequence is “1 4 3 2 5”, and K.Bro chooses “4”, he will get “1 3 2 4 5” after this round. K.Bro Sorting is similar to Bubble sort, but it’s a randomized algorithm because K.Bro will choose a random number at the beginning of each round. K.Bro wants to know that, for a given sequence, how many rounds are needed to sort this sequence in the best situation. In other words, you should answer the minimal number of rounds needed to sort the sequence into ascending order. To simplify the problem, K.Bro promises that the sequence is a permutation of 1, 2, . . . , N .
 

Input
The first line contains only one integer T (T ≤ 200), which indicates the number of test cases. For each test case, the first line contains an integer N (1 ≤ N ≤ 10 6).

The second line contains N integers a i (1 ≤ a i ≤ N ), denoting the sequence K.Bro gives you.

The sum of N in all test cases would not exceed 3 × 10 6.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1), y is the minimal number of rounds needed to sort the sequence.
 

Sample Input
  
  
2 5 5 4 3 2 1 5 5 1 2 3 4
 

Sample Output
  
  
Case #1: 4 Case #2: 1
Hint
In the second sample, we choose “5” so that after the first round, sequence becomes “1 2 3 4 5”, and the algorithm completes.
 

Source


题目大意:

冒泡排序升级版,就是多次交换算一次交换,求最少的次数。


解题思路:

简单题,直接从后面枚举到前面,如果前面小于当前遍历的数那么就要将其甩到后面来,也就意味了次数要+1.


AC代码:

#include<iostream>

using namespace std;

const int maxn = 1000005;

int a[maxn];

int main()
{
    int T;
    scanf("%d",&T);
    int Min;
    int m,i;
    int ans;
    int cnt = 0;
    while(T--)
    {
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d",&a[i]);
        }
        Min = a[m-1];
        ans = 0;
        for(i=m-2;i>=0;i--)
        {
            if(a[i] > Min) ans++;
            else
                Min = a[i];
        }
        printf("Case #%d: %d\n",++cnt,ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值