2012-11-21 21:29:47Morris

[UVA][掃描] 12535 - Probability Through Experiments

Problem B

Probability Through experiment

Time Limit: 2 seconds

 

Mathematicians have often solved problems by just doing some simulation or experiments. For example, the value of pi (p) can be approximately determined by randomly plotting points in a square that inscribes a circle. Because if the square is a 250x250 square, then its area is 62500 and the area of the inscribed circle is pi*1252=15625pi. As the points are plotted randomly, so it can be assumed that number of points inside the circle and total number points plotted in the square is proportional to their respective area. So, in this way, the value of pi can approximately be determined by counting how many points are inside the circle (Figure 1). The value of pi can even be determined using a more sophisticated experiment like the Buffon’s needle experiment (Figure 2).

 

Description: F:Archive 2012Thailand 2012problemsetb_filesimage004.jpg

Figure 1: Pi approximation by counting the number of points inside the circle

Description: F:Archive 2012Thailand 2012problemsetb_filesimage005.jpg

 

Figure 2: Buffon’s needle experiment

The two experiments mentioned above to approximately determine the value of pi could be simulated by writing a computer program very easily. It would have been nice to do this sort of experiment a lot of time (Say 1 billion billion) and get an almost perfect result but for lack of time we cannot do that in real life. In this problem, you will have to write a program that will help Professor Wu to perform a similar sort of experiment but this program may not be that straightforward.

 

Professor Neal Wu is trying to solve a classic problem using simulation: If three points are randomly plotted on the boundary of a circle, then what is the probability that they will be the three vertex of an acute triangle? Of course, this problem can be solved analytically and the result he gets is 0.25. Now, he wants to verify this result through an experiment. The result can be found approximately by plotting three random points on a circle billions of times and counting how many times these three points form an acute triangle. The beauty of such an experiment (as mentioned above) is that if we increase the number of trials, the result will become even more accurate. But if Dr. Wu wants to repeat this process 1000 billion times, it will take 2 hours of time and if he wants to repeat it a billion billion times, it may take more than 200 years. Dr. Wu has discovered that this process can be sped up by using a different approach – generate n random points on the boundary of a circle and they form Description: F:Archive 2012Thailand 2012problemsetb_filesimage006.gif triangles as vertices. How many of these triangles are acute triangles? If the number of acute triangle is M and let N = Description: F:Archive 2012Thailand 2012problemsetb_filesimage006.gif, then the desired probability is Description: F:Archive 2012Thailand 2012problemsetb_filesimage007.gif. So, given the n points on the boundary, you have to assist Dr. Wu by writing a very efficient program to find the number of acute triangles.

 

Description: F:Archive 2012Thailand 2012problemsetb_filesimage008.jpg

Figure 3: Example of a circle with given points on the boundary

Input

The input file contains around 40 test cases. But most of the cases are not extreme, so the size of the input file is around 3 MB. The description of each test case is given below:

 

Each case starts with two positive integers n (0 < n ≤ 20000) and r (0 < r ≤ 500). Here, n is the total of points on the circle boundary and r is the radius of the circle. The center of the circle is always at the origin (0,0). Each of the next N lines denotes the location of one point on the boundary of the circle. Each point is P, denoted by a floating-point number θ (0.000 ≤ θ < 360.000). This θ is actually the angle (expressed in degree) the point P creates at the center of the circle with the positive direction of x-axis. So the Cartesian coordinate of P is ( r*cos(θ), r*sin(θ)). Value of θ will always have exactly three digits after the decimal point. No two points will be at the same location.       

 

A line containing two zeroes terminates the input. This line should not be processed.

 

Output

Each test case produces one line of output. This line contains the serial of output followed by an integer. This integer denotes how many of the Description: F:Archive 2012Thailand 2012problemsetb_filesimage009.gif  triangles formed by these n points are actually acute triangles.

 

/* 20000 points generated on the boundary of a circle can actually create 20000*19999*19998/6 ~1333 billion triangles. So, of experiment for 1333 billions can be done in, say, 0.5 second. Then experiments with 1 billion billion triangles can be done in around 100 hours only (In contrast to 200 years mentioned earlier) just by repeating this experiment. Also, if we put 1817120 points on the boundary of the circle, around 1 billion billion triangles are created, and the number of acute triangles within this large number of triangles can be computed within 5 minutes. */

 

Sample Input

Sample Output

4 71

234.600

33.576

20.375

84.908

7 7

11.586

114.435

248.411

108.640

287.629

150.224

340.481

0 0

 

Case 1: 2

Case 2: 12



這題前面給了很多數學知識,不過真正要你求的是,圓周上有很多點,任取三點做三角形,有多少個銳角(acute)三角形,銳角不包括直角(right)三角形。

我代碼中好像打成 normal 了,請多多見諒。

那很簡單,找出所有畫分圓的直徑,然後抓兩個點(同一側)跟直徑上的點配成鈍角,直角我這邊是特別判斷的。

直角測資。
3 5
0.000
30.000
180.000

#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;
int x[20005];
inline int ReadInt(int *x) {
    static char c, neg;
    while((c = getchar()) < '-')    {if(c == EOF) return EOF;}
    neg = (c == '-') ? -1 : 1;
    *x = (neg == 1) ? c-'0' : 0;
    while((c = getchar()) >= '0')
        *x = (*x << 3) + (*x << 1) + c-'0';
    *x *= neg;
    return 1;
}
int main() {
    int n, r, i, j, a, b;
    int cases = 0;
    while(scanf("%d %d", &n, &r) == 2) {
        if(n == 0)  break;
        for(i = 0; i < n; i++) {
            ReadInt(&a);
            ReadInt(&b);
            x[i] = a*1000+b;
        }
        sort(x, x+n);
        long long tot = 0, t1, t2, normal = 0, ans;
        ans = (long long)n*(n-1)*(n-2)/6;
        queue<int> Q;
        for(i = 0, j = 0; i < n; i++) {
            if(x[i] >= 180000)  break;
            while(j < n && x[j] <= x[i]+180000)
                Q.push(x[j]), j++;
            while(!Q.empty() && Q.front() <= x[i])  Q.pop();
            t1 = Q.size();
            t2 = n-1-t1;
            if(j > 0 && x[j-1] == x[i]+180000)
                t1--, normal += t1+t2;
            tot += t1*(t1-1)/2;
            tot += t2*(t2-1)/2;
        }
        for(i = 0; i < n; i++) {
            x[i] += 180000;
            if(x[i] >= 360000)  x[i] -= 360000;
        }
        sort(x, x+n);
        while(!Q.empty())   Q.pop();
        for(i = 0, j = 0; i < n; i++) {
            if(x[i] >= 180000)  break;
            while(j < n && x[j] <= x[i]+180000)
                Q.push(x[j]), j++;
            while(!Q.empty() && Q.front() <= x[i])  Q.pop();
            t1 = Q.size();
            t2 = n-1-t1;
            if(j > 0 && x[j-1] == x[i]+180000)
                t1--, normal += t1+t2;
            tot += t1*(t1-1)/2;
            tot += t2*(t2-1)/2;
        }
        printf("Case %d: %lld\n", ++cases, ans-tot/2-normal/2);
    }
    return 0;
}