hdu4466 Triangle

Triangle

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 236    Accepted Submission(s): 121


Problem Description
You have a piece of iron wire with length of n unit. Now you decide to cut it into several ordered pieces and fold each piece into a triangle satisfying:
*All triangles are integral.
* All triangles are pairwise similar.
You should count the number of different approaches to form triangles. Two approaches are considered different if either of the following conditions is satisfied:
*They produce different numbers of triangles.
* There exists i that the ith (again, pieces are ordered) triangle in one approaches is not congruent to ith triangle in another plan.
The following information can be helpful in understanding this problem.
* A triangle is integral when all sides are integer.
*Two triangles are congruent when all corresponding sides and interior angles are equal.
* Two triangles are similar if they have the same shape, but can be different sizes.
*For n = 9 you have 6 different approaches to do so, namely
(1, 1, 1) (1, 1, 1) (1, 1, 1)
(1, 1, 1) (2, 2, 2)
(2, 2, 2) (1, 1, 1)
(1, 4, 4)
(2, 3, 4)
(3, 3, 3)
where (a, b, c) represents a triangle with three sides a, b, c.
 

Input
There are several test cases.
For each test case there is a single line containing one integer n (1 ≤ n ≤ 5 * 106).
Input is terminated by EOF.
 

Output
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) and Y is the number of approaches, moduled by 109 + 7.
 

Sample Input
1 2 3 4 5 6 8 9 10 11 12 15 19 20 100 1000
 

Sample Output
Case 1: 0 Case 2: 0 Case 3: 1 Case 4: 0 Case 5: 1 Case 6: 2 Case 7: 1 Case 8: 6 Case 9: 3 Case 10: 4 Case 11: 10 Case 12: 25 Case 13: 10 Case 14: 16 Case 15: 525236 Case 16: 523080925
#include <stdio.h>
#include <iostream>
#include <math.h>
#define maxmod 1000000007
#define N 5000001
using namespace std;
int dp[N],fact[N];
void init()
{
    int i,j;
    dp[3]=1;
    for(i=4;i<N;i++)
    {
        dp[i]=dp[i-1]+floor((i-1)/2.0)-ceil(i/3.0)+1;
        if(!(i&1))//如果是偶数的话
        {
            dp[i]-=floor((i/2)/2.0);
            if(dp[i]<0)
            {
                dp[i]+=maxmod;

            }
            if(dp[i]>=maxmod)
            {
                dp[i]-=maxmod;
            }
        }
    }
    fact[1]=1;fact[2]=2;
    for(i=3;i<N;i++)
    {
      fact[i]=fact[i-1]*2;//记录2的阶乘
      if(fact[i]>=maxmod)
      {
          fact[i]-=maxmod;
      }
      for(j=2;i*j<N;j++)
      {
          dp[i*j]-=dp[i];//去掉所有的非质三角形,一定要从小去,
          if(dp[i*j]<0)
          {
              dp[i*j]+=maxmod;
          }
      }
    }


}
int main ()
{
    int i,n,tcase;
    __int64 result;
    tcase=1;
    init();
    while(scanf("%d",&n)!=EOF)
    {
        result=0;
        for(i=1;i*i<=n;i++)
        {
            if(n%i==0)//可以分成n/i个小三角形
            {
                result=(result+(__int64)dp[i]*fact[n/i]%maxmod)%maxmod;
                if(i*i!=n)//i与n/i不相等,就要加两个
                {
                result=(result+(__int64)dp[n/i]*fact[i]%maxmod)%maxmod;
                }
            }

        }

        printf("Case %d: %I64d\n",tcase++,result);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值