数学推导——ACdream 1067

  • 题目链接: http://acdream.info/problem?pid=1067

  • 题意: 在圆上取N个点,以至将圆弧分成N等份,求任取3个点能构成多少个锐角三角形

  • 分析: 当3个点组成锐角三角形ABC时,圆心O一定在三角形内部,∠AOB , ∠BOC, ∠COA一定小于180度(∠AOB + ∠BOC + ∠COA = 360度)

  • (1)当N为偶数时,用1, 2 …. k , k+1, …. , 2k来标记N个点(2K = N). 固定一个点, 如点A = 点k, 那么2k点是肯定不能选的了,因为 k, 2k组成一条直径。

  • 所以剩下两个区间 [1, k-1], [K+1, 2k-1].如果点B, 点C同处一个区间,那么ABC一定是一个钝角三角形,所以B,C一定不可处于同一区间。

  • 设点B = 点x, x 属于[1, k-2]; 点C=点y,y 属于[k+1, 2k-1];

  • 在这样的情况下,y - x > k 才能使得ABC为锐角三角形 ==> (x, y)的取值有S = 0 + 1 + 2 + … + (k - 2) = (k -1) * (k -2) /2 = (N/2 - 1) * (N / 2 - 2) / 2 ;

  • 有N个点,每个三角形被重复计算3次,所以一共有 S * N / 3种;

  • (2)点N为奇数时, k = N / 2. 用0, 1 … k , k + 1, 2k.

  • 固定点A = 点0,则过点A的直径把N个点分成[1, k], [k+1, 2k]两个部分。和(1)同理,可以令 点B = 点x , x 属于[1, k], 点C = 点y, y 属于[k+1, 2k];

  • AC代码:

/*************************************************************************
    > File Name: test.cpp
    > Author: Akira 
    > Mail: [email protected] 
 ************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;

#define MaxN 100000
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define bug cout<<88888888<
#define MIN(x,y) (x
#define MAX(x,y) (x>y?x:y)

template<typename _> inline void scan(_& t)
{
    int c;
    while((c = getchar()) < '0' || c > '9');
    t = c - '0';
    while((c = getchar()) >= '0' && c <= '9') t = t * 10 + c - '0';
}
template<typename _> inline void print(_ x)
{
    int len = 0, p[20];
    if(x < 0) putchar('-'), x = -x;
    while(x) p[++len] = x % 10, x /= 10;
    if(!len) p[++len] = 0;
    while(len) putchar(p[len--] + '0');
}
/*
3 1
4 0
5 5
6 0
7 7
8 8
9 9
10
n奇数:n*(n/2)*(n/2+1)/6;
n偶数:n*(n/2-1)*(n/2-2)/6; 
*/

LL N;
int main()
{
    while(~scanf("%lld", &N))
    {
        LL ans;
        if(N&1)
        {
            ans = N*(N/2)*(N/2+1)/6;
        }
        else
        {
            ans = N*(N/2-1)*(N/2-2)/6;
        }
        printf("%lld\n", ans);
    }
    //system("pause");
}

你可能感兴趣的:(ACM算法(题解):,数学)