HDU 4466 Triangle

Triangle

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

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

题意

长度为的铁丝,你可以将其分成若干段,并把每段都折成一个三角形。你还需要保证三角形的边长都是正整数并且三角形两两相似,问有多少种不同的分法。

题解

设w[i]为长度为i的铁丝的分法,一种分法的所有三角形边长除以gcd(a,b,c)得到的三角形都一样,且三边互质,设边长为a’,b’,c’。

若M=a+b+c,M’=a’+b’+c’,设k=M/M’,那么以a’,b’,c’为三边的三角形为基,用长度为M的铁丝能做出的方案数为2^(k-1)。

设g[i]为长度为i的铁丝分成边长为a,b,c(a<=b<=c)且gcd(a,b,c)=1的三角形的方案数。

那么w[i]=g[p1]*2^(i/p1-1)+g[p2]*2^(i/p2-1)+…+g[pk]*2^(i/pk-1)(p为i的因数且p>=3)。

例:w[12]=g[12]*1+g[6]*2+g[4]*4+g[3]*8。

设f[i]为长度为i的铁丝分成边长为a,b,c(a<=b<=c)的三角形的方案数。

那么g[i]=f[i]-g[p1]-g[p2]-…-g[pk](p为i的因数且p!=i且p>=3)。

例:g[12]=f[12]-g[6]-g[4]-g[3]。

考虑如何求f[i]。

分两种情况:

1.b==c,c最小为ceil(i/3),最大为floor((i-1)/2) 。

2.b<c,那么就是求a<=b<=c-1的方案数,为f[i-1]。

第二种情况还要除去a+b=c的方案数。

若a+b=c,那么i=a+b+c=2*(a+b),a+b=i/2,这样的(a,b)有i/2/2对,此时i一定为偶数,所以i为偶数时要考虑这种情况。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=5000005,mod=1000000007;
int n,ans,cnt;
int f[N],p[N];
int main(){
	p[1]=1;
	for(int i=2;i<=N;i++)p[i]=(p[i-1]*2)%mod;
	f[3]=1;
	for(int i=4;i<=N;i++){
		f[i]=f[i-1]+(i-1)/2-i/3+(i%3?0:1);
		if(i%2==0)f[i]-=i/4;
		f[i]%=mod;
		if(f[i]<0)f[i]+=mod;
	}		
	for(int i=2;i<=N;i++)
		for(int j=2;i*j<=N;j++){
			f[i*j]-=f[i];
			if(f[i*j]<0)f[i*j]+=mod;
		}
	while(~scanf("%d",&n)){
		ans=0;
		for(int i=1;i*i<=n;i++){
			if(n%i!=0)continue;
			ans=(ans+1ll*f[i]*p[n/i])%mod;
			if(i*i!=n)ans=(ans+1ll*f[n/i]*p[i])%mod;	
		}
		printf("Case %d: %d\n",++cnt,ans);		
	}
	return 0;
}

转载于:https://www.cnblogs.com/chezhongyang/p/7648116.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值