HDU4651|HDU1028 Partition 整数拆分公式法

52 篇文章 0 订阅
21 篇文章 0 订阅

题目链接:HDU4651

题目大意:给你n,求出n的拆分数,例如p(4)=5  4=1+1+1+1 ,4=1+1+2 , 4=1+3, 4=2+2,4=4;五种拆分,无序。

知识点:

1、广义五边形数:广义五边形数

广义五边形数的公式和五边形数相同,只是n可以为负数和零,n 依序为0, 1, -1, 2, -2, 3, -3, 4...,广义五边形数也可以用下式表示:

{\displaystyle p_{n}={\frac {3n^{2}\pm n}{2}}}{\displaystyle p_{n}={\frac {3n^{2}\pm n}{2}}}

n 依序为0, 1, 2, 3, 4...,

其产生的数列如下:

0, 1, 2, 5, 7, 12, 15, 22, 26, 35, 40, 51, 57, 70, 77, 92, 100, 117, 126, 145, 155, 176, 187, 210, 222, 247, 260, 287, 301, 330, 345, 376, 392, 425, 442, 477, 495, 532, 551, 590, 610, 651, 672, 715, 737, 782, 805, 852, 876, 925, 950, 1001, 1027, 1080, 1107, 1162, 1190, 1247, 1276, 1335... (OEIS:A001318)

欧拉整数分拆理论中,五边形数定理说明广义五边形数和整数分拆的关系。

用第n个五边形数(n>2)排列组成的正五边形,外围点的个数有{\displaystyle 5(n-1)}{\displaystyle 5(n-1)}个,因此在内部的点个数为:

{\displaystyle {\frac {3n^{2}-n}{2}}-5(n-1)={\frac {3n^{2}-11n+10}{2}}={\frac {(3n-5)(n-2)}{2}}={\frac {3(n-2)^{2}+(n-2)}{2}}}{\displaystyle {\frac {3n^{2}-n}{2}}-5(n-1)={\frac {3n^{2}-11n+10}{2}}={\frac {(3n-5)(n-2)}{2}}={\frac {3(n-2)^{2}+(n-2)}{2}}}

刚好也是一个广义五边形数。

所有的整数都可以表示成不超过3个广义五边形数的和[1]

若三角形数可以被3整除,则除以3之后的数必为广义五边形数[2]

2、

整数拆分的公式

{\displaystyle p(n)}生成函数

{\displaystyle \sum _{n=0}^{\infty }p(n)x^{n}=\prod _{k=1}^{\infty }\left({\frac {1}{1-x^{k}}}\right)}{\displaystyle \sum _{n=0}^{\infty }p(n)x^{n}=\prod _{k=1}^{\infty }\left({\frac {1}{1-x^{k}}}\right)}

当|x|<1,右边可写成:

{\displaystyle (1+x+x^{2}+x^{3}+...)(1+x^{2}+x^{4}+x^{6}+...)(1+x^{3}+x^{6}+...)...}{\displaystyle (1+x+x^{2}+x^{3}+...)(1+x^{2}+x^{4}+x^{6}+...)(1+x^{3}+x^{6}+...)...}

{\displaystyle p(n)}{\displaystyle p(n)}生成函数的倒数为欧拉函数,利用五边形数定理可得到以下的展开式:

{\displaystyle \prod _{k=1}^{\infty }(1-x^{k})=\sum _{i=-\infty }^{\infty }(-1)^{i}x^{i(3i-1)/2}.}{\displaystyle \prod _{k=1}^{\infty }(1-x^{k})=\sum _{i=-\infty }^{\infty }(-1)^{i}x^{i(3i-1)/2}.}

{\displaystyle p(n)}{\displaystyle p(n)}生成函数配合五边形数定理,可以得到以下的递归关系式

{\displaystyle p(n)=\sum _{i}(-1)^{i-1}p(n-q_{i})}{\displaystyle p(n)=\sum _{i}(-1)^{i-1}p(n-q_{i})}

其中{\displaystyle q_{i}}q_i是第{\displaystyle i}i广义五边形数

3、就是利用最后一个公式来做题。注意的是qi是两个部分,最后一个公式也可以写成

然后根据这个公式把样例手算一下 ,就很清晰了。

AC代码

/*
整数拆分 公式法 
打表
2017年8月3日00:15:14
AC代码


*/ 

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;

const int mod=1e9+7;
const int maxn=1e5+10; 
ll ans[maxn];
int t,n;
void init(){
	memset(ans,0,sizeof(ans));
	ans[0]=1;
	
	for(int i=1;i<=maxn;i++){
		int f;//代表这一位是加还是捡 
		for(int j=1;;j++){
			int a,b;
			/*i减去对应的两个广义五边形数*/ 
			a=i-j*(3*j-1)/2;
			b=i-j*(3*j+1)/2;
			/*根据i判定这一位的正负*/
			if(j&1) f=1;//奇数 加 
			else 	f=-1;//偶数 减
			/*坑点,如果两个p(n-qi)都小于零,那么就加到这里为止*/ 
			if(a<0&&b<0) break;
			/*任何一个p(n-qi)大于零都要算进去*/
			if(a>=0) ans[i]=(ans[i]+f*ans[a]) %mod;
			if(b>=0) ans[i]=(ans[i]+f*ans[b]) %mod;
		}
		ans[i]=(ans[i]+mod)%mod;
	}
	
}

int main(){
	cin.sync_with_stdio(false);
	cin>>t;
	init(); 
	while(t--){
		cin>>n;
		cout<<ans[n]<<endl;
	}
	return 0;
}


再来一个同类型的题目HDU1028

与上面不同的是,不需要模直接输出即可,AC代码


/*
2017年8月16日10:07:18
HDU1028
AC 

*/
#include<stdio.h>  
#include<iostream>  
#include<string.h>  
using namespace std;  
typedef long long ll;  
  
//const int mod=1e9+7;  
const int maxn=1e5+10;   
ll ans[maxn];  
int t,n;  
void init(){  
    memset(ans,0,sizeof(ans));  
    ans[0]=1;  
      
    for(int i=1;i<=maxn;i++){  
        int f;//代表这一位是加还是捡   
        for(int j=1;;j++){  
            int a,b;  
            /*i减去对应的两个广义五边形数*/   
            a=i-j*(3*j-1)/2;  
            b=i-j*(3*j+1)/2;  
            /*根据i判定这一位的正负*/  
            if(j&1) f=1;//奇数 加   
            else    f=-1;//偶数 减  
            /*坑点,如果两个p(n-qi)都小于零,那么就加到这里为止*/   
            if(a<0&&b<0) break;  
            /*任何一个p(n-qi)大于零都要算进去*/  
            if(a>=0) ans[i]=(ans[i]+f*ans[a]) ;  
            if(b>=0) ans[i]=(ans[i]+f*ans[b]) ;  
        }  
        //ans[i]=(ans[i]+mod)%mod;  
    }  
      
}  
  
int main(){  
    cin.sync_with_stdio(false);  
   // cin>>t;  
    init();   
    while(cin>>n){  
         
        cout<<ans[n]<<endl;  
    }  
    return 0;  
}  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值