hdu4466 将长度为n线段瓜分成若干个相似三角形,有多少种分法(划分dp)

47 篇文章 0 订阅
15 篇文章 0 订阅

三角形顺序不同视为不同方案。

题解:http://www.cnblogs.com/jianglangcaijin/p/3465526.html

#include<bits/stdc++.h>
#define ll long long  
#define mod 1000000007
#define maxn 5000000
using namespace std;   
int dp[maxn+5];
int power[maxn+5];
int main(){
	power[0]=1;
	for(int i=1;i<=maxn;++i)
		power[i]=power[i-1]*2%mod;
	dp[3]=1;
	for(int i=4;i<=maxn;++i){ 
		dp[i]+=(i-1)/2-ceil(i/3.0)+1; //b=c:最少时靠近等边三角形,最多时最短边靠近1 
		dp[i]+=dp[i-1]; //b<c:不考虑c保底的1,(a,b,c)在b<c时的个数=(a,b,c-1)的总个数再减去 
		//a+b=(c-1)+1时(a,b,c-1)还原后取不到三角形时的个数,因为a+b+c=i,所以化简得c=i/2。 
		if(i%2==0)
			dp[i]=dp[i]-(i/2)/2+mod; //因为a+b已经确定,所以ab的取法只有floor(c/2)
		dp[i]%=mod;
	}
	//枚举最小的三角形的周长可能取值,会发现gcd(a0,b0,c0)=1,因为要保证其它都是它的倍数 
	//不然的话(6,9,9)不会是(4,6,6)的倍数,而应该是(2,3,3) 
	//因此,首先要预处理,把dp[]里面那些gcd!=1的情况去掉。这里用了一种类似筛选法的方法。
	for(int i=3;i<=maxn;++i){
		for(int j=i*2;j<=maxn;j+=i)
			dp[j]=(dp[j]-dp[i]+mod)%mod;
	} 
	int n,cnt=0;
	while(scanf("%d",&n)!=EOF){
		ll s=0;
		for(int i=1;i*i<=n;++i){ //枚举最小的单位三角形的周长可能取值
			if(n%i==0){
				int w=n/i-1; // n/i颗球有n/i-1个缝隙 
				s=(s+(ll)power[w]*dp[i])%mod; //Cn0-Cn1+Cn2-Cn3+……+(-1)^nCnn=0
				
				if(i*i!=n){
					w=i-1;  
					s=(s+(ll)power[w]*dp[n/i])%mod; //Cn0-Cn1+Cn2-Cn3+……+(-1)^nCnn=0
				}
			}
		}	
		printf("Case %d: %I64d\n",++cnt,s);
	}
	return 0;
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值