第一题
很简单随便写
第二题
给一个整数N(3<=N<=10^7),求正N多边形中有多少个等腰锐角三角形。
实例:N=3
答案:1
实例:N=4
答案:0
实例:N=5
答案:5
以下给出两种解法:
- 暴力法 O(N)
从一个点A出发,同时向两侧移动,两侧点分别为B和C,AB和AC组成等腰边,BC组成底边。
当BAC占有正N多边形的边数大于BC占有的边数时,ABC组成等腰锐角三角形。
cnt 开始计数,并继续逐个点移动,直到BC点重合。
特殊情况:当ABC组成等边三角形时,另外两个点计算时会有重复的结果,因此需额外判断N是不是三的倍数
因此有:res = cnt*N - (N/3*2 if N%3 == 0 else 0) - 数学法 O(1)
简单的把暴力法转换为数学法。
minAB = minAC = N/4 + 1 :等腰边最小跨过的N边形边数
maxBC = N - minAB - minAC = N - (N/4 + 1) * 2 :底边最长的长度
因此 底边长度可以为以下值
maxBC, maxBC-2, maxBC-4 … 1 :当maxBC%2 == 1
maxBC, maxBC-2, maxBC-4 … 2 :当maxBC%2 == 0
所以有
cnt = ceil( (N - (N/4 + 1) * 2) / 2)
同时考虑特殊情况:当ABC组成等边三角形时,另外两个点计算时会有重复的结果,因此需额外判断N是不是三的倍数
因此有:res = cnt*N - (N/3*2 if N%3 == 0 else 0)
#include <iostream>
#define LL long long
using namespace std;
LL ViolenceToSolve(int N)
{
LL res = 0;
LL cnt = 0;
for(int i=1; i<=N/2; ++i)
{
if(N-i*2>0 && N-i*2<i*2)
{
++cnt;
}
}
res = cnt*N;
if(N%3 == 0)
{
res -= N/3*2;
}
return res;
}
LL MathToSolve(int N)
{
LL res = 0;
LL cnt = 0;
cnt = N - (N/4*2+2);//底边maxBC
cnt = cnt/2 + cnt%2;//ceil操作
res = cnt*N;
if(N%3 == 0)
{
res -= N/3*