HPUOJ Triangles

问题 A: Triangles
时间限制: 1 Sec 内存限制: 128 MB
题目描述
已知一个圆的圆周被N个点分成了N段等长圆弧,求任意取三个点,组成锐角三角形的个数。

输入
多组数据,每组数据一个N(N <= 1000000)

输出
对于每组数据,输出不同锐角三角形的个数。

样例输入
3
4
5
样例输出
1
0
5

解法一:计算锐角三角形的个数,可以用总的三角形的个数减去直角三角形和钝角三角形的个数即可。
C(n,3)-C(n/2,2)2n/2
全部不同三角形个数为 C(n,3)
每个点能构成的不同钝角或者三角形个数为 C(n/2,2),每个点拉一条直径,钝角或者直角三角形的其他两点只能在直角一侧,直径一侧所有点除所取点任意选两个的不同方案数,另一半同理。
全部构成的不同钝角或者三角形个数为 C(n/2,2)2n/2
n个点,每个三角形可以被构成两次。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
ll n,k,ans,sum,tot;
int main()
{
    while(scanf("%lld",&n)!=EOF)
    {
        sum=n*(n-1)*(n-2)/6;
        k=n/2;
        tot=k*(k-1)/2*2*n/2;
        ans=sum-tot;
        cout << ans << endl;
    }

    return 0;
}

解法二:
可以分为两种情况:n为偶数和n为奇数
1.n为偶数时,假设点的标号为1,2,3…k,k+1…2k;2k=n,取一个点作为三角形的一个顶点a,a取k,那么2k就不能再取了,因为k与2k连接为一条直径,直径所对的角为直角,此时圆被分成了两个区域[1,k-1]和[k+1,2k-1];三角形的另外两个顶点x,y,取自不同区域时为锐角,所以假设x=[1,k-1],y=[k+1,2k-1],且y-x>k时,构成锐角三角形。
y x 个数
k+1 没有符合的值 0
k+2 1 1
k+3 1,2 2
k+4 1,2,3 3
… … …
2k-1 1,2…(k-2) k-2
s=1+2+3+…k-2=(k-1)(k-2)/2,and k=n/2 so…s=
(n/2-1)
(n/2-2)/2
有n个点,每个三角形算了3遍,so…num=sn/3;
2.n为奇数时,假设点的标号为0,1,2。。。2k,取0作为三角形的一个顶点,以该点画一条直径,将圆分成两个区域:[1,k],[k+1,2k],另外两个顶点不在同一个区域且y-x<=k时,三角形为锐角三角形
y x 个数
k+1 1,2…k k
k+2 2,3…k k-1
… … …
2k k 1
s=(k+1)k/2; k=n/2;s=(n/2+1)(n/2)/2 num=s
n/3=
(n/2+1)*(n/2)/6
思路:以此为例,分奇偶讨论,就是一个公差为1的等差数列;
由于构成锐角三角形,过某一点画中轴线,另外两点必不能在同一侧或者中轴线上,只能在两侧,找出两侧的点可以组成多少个满足条件的锐角三角形,最后除以3(因为每个点备用三次)

参考代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
ll n,k,ans;
int main()
{
    while(scanf("%lld",&n)!=EOF)
    {
        if(n<3)
            cout << 0 << endl;
        else if(n%2==0)
        {
            k=n/2;
            ans=(k-1)*(k-2)/2*n/3;
            cout << ans <<endl;
        }
        else if(n%2==1)
        {
            k=(n-1)/2;
            ans=(k+1)*k/2*n/3;
            cout << ans << endl;
        }
    }

    return 0;
}

#include<cstdio>
int main()
{
	long long n,m,ans,tot;
	while(scanf("%lld",&n)!=EOF)
	{
		if(n<3 || n==4) printf("0\n");
		else if(n%2==0)
		{
			m=(n-2)/2;//减去中轴线上的点,其次讨论一侧即可;
			ans=(0+m-1)*m/2;//等差数列;
			tot=ans*n/3;//n个点,每个点用了三次;
			printf("%lld\n",tot);
		}
		else if(n%2==1)//同上,但是数列的起始不同;
		{
			m=(n-1)/2;
			ans=(0+m)*(m+1)/2;
			tot=ans*n/3;
			printf("%lld\n",tot);
		}
	}
	return 0;
}
#include<cstdio>
int main()
{
    long long n,num;
    while(~scanf("%lld",&n)){
    if(n<3) num=0;
    else if(n%2==0) num=(n/2-2)*(n/2-1)*n/6;
    else num=(1+n/2)*(n/2)*n/6;
    printf("%lld\n",num);
    }
    return 0;}

猜你喜欢

转载自blog.csdn.net/w1304636468/article/details/89837886
今日推荐