zoukankan      html  css  js  c++  java
  • 【hdu 4658】Integer Partition (无序分拆数、五边形数定理)

    hdu 4658 Integer Partition

    题意

    n分拆成若干个正整数的和,每个正整数出现小于k次,分拆方案有多少。(t<=100,n<=1e5)

    题解

    之前写过一篇Partition Numbers的计算,后面补充了hdu 4651的做法。就是利用五边形数定理。
    这题加强了限制条件。

    n的无序分拆数的生成函数:
    (sum_{i=1}^{infty}B(i)x^i=(1+x+x^2+..)(1+x^2+x^4+..)…=frac {1}{prod_{i=1}^{infty}(1-x^i)})

    由五边形数定理知

    (prod_{n=1}^{infty}(1-x^n)=sum_{k=0}^infty (-1)^k x^{frac {k(3kpm 1)}{2}})

    ((1+B(1)x+B(2)x^2+..)(1-x-x^2+x^5+x^7+..)=1)

    比较两边(x^n)系数,得到

    (B(n)-B(n-1)-B(n-2)+B(n-5)+B(n-7)+..=0)

    所以可以(O(n^{1.5}))计算出B。

    有了限制,生成函数变成
    (g(x)=(1+x+x^2+..+x^{k-1})(1+x^2+x^4+..+x^{2(k-1)})…= {prod_{i=1}^infty(1-x^{ik})}B(x))

    再利用五边形数定理得

    (g(x)=(1-x^k-x^{2k}+x^{5k}+..)(1+B(1)x+B(2)x^2+B(3)x^3+..))

    (x^n)的系数即为答案。

    代码

    int n,k;
    int B[N]={1,1,2};
    int main() {
    	int t;
    	sf(t);
    	for(int i=3;i<N;++i)
    	for(int j=1,f=1;f;++j)
    	for(int k=-1;k<2;k+=2){
    		int w=(3*j*j+k*j)/2;
    		if(w>i){f=0;break;}
    		if(j%2)B[i]=(B[i]+B[i-w])%mod;
    		else B[i]=(B[i]-B[i-w]+mod)%mod;
    	}
    	while(t--){
    		sf(n);sf(k);
    		int ans=0;
    		ans=B[n]%mod;
    		for(int i=1,f=1;f;++i)
    		for(int j=-1;j<2&&f;j+=2){
    			int w=(3*i*i+j*i)/2;
    			if(w*k>n){f=0;break;}
    			if(i%2==0)ans=(ans+B[n-w*k])%mod;
    			else ans=(ans-B[n-w*k]+mod)%mod;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    互斥量
    读写锁
    死锁
    pthread
    线程
    守护进程
    信号捕捉
    信号集
    信号
    mmap
  • 原文地址:https://www.cnblogs.com/flipped/p/7475488.html
Copyright © 2011-2022 走看看