题目:
一个三角形,每条 边的长度都是1到N中的正整数,这三条边能组成多少个不同的三角形呢
n
≤
1
0
9
n\le 10^9
n≤109
solution:
啊这就是个妥妥的高中数学题,涉及到数列,几何等知识
设
f
[
n
]
f[n]
f[n]为答案,
f
[
n
]
=
f
[
n
−
1
]
+
g
[
n
]
f[n]=f[n-1]+g[n]
f[n]=f[n−1]+g[n]
g
[
n
]
g[n]
g[n]就是至少一条边是
n
n
n的时候的合法方案数
然后设
h
[
i
,
n
]
h[i,n]
h[i,n]表示在
g
[
n
]
g[n]
g[n]的条件下另一条边是
i
i
i的第三条边的个数
分类讨论若
i
≤
(
n
+
1
)
/
2
i \le (n+1)/2
i≤(n+1)/2那么
h
[
i
]
=
i
h[i]=i
h[i]=i
否则
h
[
i
]
=
n
−
i
+
1
h[i]=n-i+1
h[i]=n−i+1
然后就是推式子,几个小
t
r
i
c
k
trick
trick都是高中数列知识
最后的答案就是,设
k
=
(
n
+
1
)
/
2
k=(n+1)/2
k=(n+1)/2
若
n
n
n为偶数,
a
n
s
=
k
×
(
k
+
1
)
×
(
4
×
k
+
5
)
ans=k\times (k+1)\times (4\times k+5)
ans=k×(k+1)×(4×k+5)
若
n
n
n为奇数,
a
n
s
=
k
×
(
k
+
1
)
×
(
4
×
k
−
1
)
ans=k\times (k+1)\times (4\times k-1)
ans=k×(k+1)×(4×k−1)
还有注意到这是
n
3
n^3
n3级别的,要用高精度!!!
顺便打了打高精度板子,虽然不怎么优美,但加减乘除都有了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
int n;
struct High_precision{
int a[100],len;
High_precision(){memset(a,0,sizeof a);len=0;}
void clear(){
while(!a[len] && len>1) len--;
}
High_precision operator +(const High_precision &x) const{
High_precision ret;
ret.len=max(len,x.len);
for(int i=1;i<=ret.len;i++)
ret.a[i]=a[i]+x.a[i];
for(int i=1;i<=ret.len;i++)
if(ret.a[i]>9) ret.a[i]-=10,ret.a[i+1]++;
while(ret.a[ret.len+1]) ret.len++;
ret.clear(); return ret;
}
High_precision operator -(const High_precision &x) const{
High_precision ret;
ret.len=len;
for(int i=len;i;i--)
if(i<=x.len) ret.a[i]=a[i]-x.a[i];
else ret.a[i]=a[i];
for(int i=1;i<=ret.len;i++)
if(ret.a[i]<0) ret.a[i]+=10,ret.a[i+1]--;
ret.clear(); return ret;
}
High_precision operator *(const High_precision &x) const{
High_precision ret;
ret.len=len+x.len-1;
for(int i=1;i<=len;i++)
for(int j=1;j<=x.len;j++)
ret.a[i+j-1]+=a[i]*x.a[j];
for(int i=1;i<=ret.len;i++)
if(ret.a[i]>9)
ret.a[i+1]+=ret.a[i]/10,ret.a[i]%=10;
while(ret.a[ret.len+1]) ret.len++;
ret.clear(); return ret;
}
High_precision operator /(const int &x) const{
High_precision ret;
ret.len=len; int y=0;
for(int i=len;i;i--){
ret.a[i]=(y*10+a[i])/x;
y=(y*10+a[i])%x;
}
ret.clear();
if(ret.len==0) ret.len=1,ret.a[1]=0;
return ret;
}
void print(){
for(int i=len;i;i--) printf("%d",a[i]);puts("");
}
}f,g;
int main(){
scanf("%d",&n);
if(n==1) return puts("1"),0;
if(n==0) return puts("0"),0;
LL k=(n+1)>>1;
LL tmp=k*(k+1);
while(tmp){
f.len++; f.a[f.len]=tmp%10; tmp/=10;
}
if(n&1) tmp=k*4-1;
else tmp=4*k+5;
while(tmp){
g.len++; g.a[g.len]=tmp%10; tmp/=10;
}
f=f*g; f=f/6;
f.print();
return 0;
}