HDOJ 4466 Triangle 递推

66 篇文章 0 订阅


1、当b=c时,a至少为1,所以c<=(n-1)/2

而a<=b 所以n-2*c<=c =>c>=n/3; 故共有(n-1)/2-(n/3)+(n/3?0:1)种。

2、当b<c时,肯定有b<=c-1 

此时若a+b>c 则a+b>c-1 

如果a,b,c能构成三角形,则a,b,c-1也一定能够构成三角形。

反过来,如果a,b,c-1能够构成三角形,也即a+b>c-1 当a+b!=c时,一定能使a,b,c构成三角形。故可以通过dp[n-1]递推过来,然后减去a+b=c+1的情况。

此时n=2*c+1,c=(n-1)/2  只有当n为奇数的时候才有可能,而a+b=(n-(n-1)/2),a<=b 所以这种情况共有 (n-(n-1)/2)/2种,化简得(n+1)/4


在考虑有多个三角形的情况。

假设N=a*b 则把b作为一个基本三角形,a个1,作为a个部分,中间有a-1个隔板,每个隔板可选可不选,一共有2^(a-1)种情况。



Triangle

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


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 i th (again, pieces are ordered) triangle in one approaches is not congruent to i th 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 * 10 6).
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 10 9 + 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
 

Source
 


/* ***********************************************
Author        :CKboss
Created Time  :2015年09月03日 星期四 10时58分13秒
File Name     :HDOJ4466.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

const int maxn=5001000;
const int mod=1e9+7;

int n;
LL dp[maxn];
int bb[maxn];

void init()
{
	dp[3]=1LL;
	for(int i=4;i<maxn;i++)
	{
		dp[i]=dp[i-1]+(i-1)/2-i/3+(i%3?0:1);
		if((i&1)==0) dp[i]-=i/4;
		dp[i]=(dp[i]+mod)%mod;
	}
	bb[1]=1LL;
	for(int i=2;i<maxn;i++)
	{
		bb[i]=(bb[i-1]<<1)%mod;
		for(int j=2;i*j<maxn;j++)
		{
			dp[i*j]=(dp[i*j]-dp[i]+mod)%mod;
		}
	}
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	init();

	int cas=1;
	while(scanf("%d",&n)!=EOF)
	{
		LL ans=0;
		for(int i=1;i*i<=n;i++)
		{
			if(n%i==0)
			{
				int d=n/i;
				ans=(ans+(dp[i]*bb[d])%mod)%mod;
				if(i*i!=n) ans=(ans+(dp[d]*bb[i])%mod)%mod;
			}
		}
		printf("Case %d: %lld\n",cas++,ans);
	}
    
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值