简单三角形计数数学题-hdu-4486-Pen Counts

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4486

题目意思:

给一个长度len,求把len分成三段凑成三角形的个数,如果是等腰三角形记1种,非等腰的记两种。

解题思路:

三角形计数。比赛的时候傻逼的用o(n^2)的暴力方法打表,虽然过了,不能更弱。。。-_- -_-  ! ==思路不行,马上转化,不要陷入死胡同。不受不正确思路影响。之前应该见过这样的计数的。。。。

分几种情况考虑:记三边为a<=b<=c

1、当n%3==0时,可能为等边三角形 +1

2、当a=b<c时,由a+b>c得2a>c  即2a>n-2a  得a>n/4   又由a<c得 a<n-2a 得a<n/3  综合得 n/4<a<n/3 对于每一个a总能构造一种。

3、当a<b=c时,由c>a得c>n-2c 即c>n/3   又b+c<n得 c<n/2  综合得 n/3<c<n/2 对于每一个c总能唯一构造一种。

4、当a<b<c时,枚举a(1~n/3) ,  由a<b<n-a-b 得b<(n-a)/2   由a+b>c   a+b>n-a-b  得b>(n-2a)/2   综合得  max(a,(n-2a)/2)<b<(n-a)/2   a、b确定了三角形也就唯一确定了。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
int n;
int up,dow;

int uup(int x,int div) //返回<x/div的上届整数
{
   if(x%div==0)
      return x/div-1;
   return x/div;
}
int ddow(int x,int div)//返回>x/div的下届整数
{
   return x/div+1;
}
int main()
{
   int t,d;

   scanf("%d",&t);
   while(t--)
   {
      scanf("%d%d",&d,&n);
      int ans=0;
      if(n%3==0)
         ans+=1; //当a=b=c时的情况
      //printf("1:%d\n",ans);
      up=uup(n,3);
      dow=ddow(n,4);
      if(up>=dow)
         ans+=(up-dow+1); //当a=b<c时的情况
     // printf("2:%d\n",ans);
      up=uup(n,2);
      dow=ddow(n,3);
      if(up>=dow)
      ans+=(up-dow+1); //当a<b=c时的情况
     // printf("3:%d\n",ans);
      for(int a=1;a<n/3;a++) //当a<b<c时的情况
      {
         dow=ddow(a,1);
         int tmp=ddow(n-2*a,2);
         up=uup(n-a,2);
         dow=max(dow,tmp);
         if(up>=dow)
            ans+=(2*(up-dow+1));
      }
      printf("%d %d\n",d,ans);

   }
   return 0;
}




你可能感兴趣的:(数学)