问题 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=sn/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;}