uva 11401思维+预处理

1.题意描述

给定边长为1,2,3,····n的n条边,现在要在里面任意选取三条边构成三角形,我们需要求一共可以构成多少个三角形?

2.题目分析

首先我们分析数据大小问题,由于数据最大可以达到10^6。所以我们如果直接枚举时间复杂度可以达到O(n^3),那么我们可以肯定的说这个时间复杂度肯定是不能承受的。

那么我们可以根据前面求整理的排列组合公式的求二项式系数的方法联想到使用递推法。这样时间复杂度可以降低到O(n)。这是可以承受的。要想用递推法,我们肯定需要使用打表的方法----预处理,那么空间复杂度肯定是O(n)同样可以承受。现在我们分析怎样使用递推法:

我们先定义一个函数f(n):当最大编程为n时所能构成的三角形数目。

对于三角形的三边而言,我们可以设定为x,y,z。并且我们假设x是最大边。那么我们有y+z>x,因此可以推出x-y<z<x。

根据这个不等式我们有,当y=1时,显然无解;当y=2时,有一个解;当y=3时,有两个解;·····当y=x-1时有x-2个解。根据等差数列求和公式我们有一共有

0+1+2+······+(x-2)=(x-1)(x-2)/2。但是我们需要注意,这里包含了y=z情况。那么我们需要减去从y=x/2+1开始到y=x-1为止,此时我们多计数了(x-1)-(x/2+1)+1=(x-1)/2个解,而且除此之外,我们对于每一个y我们都有重复计数,因为前后是对称的。所以我们最后还要除以2得到最终结果。

最终结果为:

          

那么最后的递推式我们可以写为:

          

到这里基本分析完毕。

wa的第一点  数组超了,后面还存了10000005

wa的第二点  数据爆了,不要强制转换,直接定义i为longlong 

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 long long f[1000001];//wa的第一点  数组超了,后面还存了10000005 
 6 int main()
 7 {
 8     //先打表预处理
 9     f[3]=0;
10     for(int i=4;i<=1000005;i++)
11     f[i]=f[i-1]+(long long)(((i-1)*(i-2)/2-(i-1)/2)/2);// wa的第二点  数据爆了,不要强制转换,直接定义i为longlong 
12     int n;
13     while(~scanf("%d",&n))
14     {
15         if(n<3)
16         break;
17         cout<<f[n]<<endl;
18      } 
19  } 

ac代码:

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long long f[1000010];
int main()
{
	//先预处理
	 f[3]=0;
	for(long long i=4;i<=1000005;i++)
	f[i]=f[i-1]+((i-1)*(i-2)/2-(i-1)/2)/2;
	int n;
	while(~scanf("%d",&n))
	{
		if(n<3)
		break;
		cout<<f[n]<<endl;
	 } 
 } 

  

转载于:https://www.cnblogs.com/Aiahtwo/p/10921530.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值