1. 程式人生 > >hdu 4658 Integer Partition

hdu 4658 Integer Partition

p k ( x ) p_k(x) 表示具有限制 k

k 的劃分計數的生成函式, p ( x ) p(x) 表示沒有限制的劃分計數的生成函式。
p
k ( x ) = i =
1
( 1 + x i + x 2 i + . . . + x ( k 1 ) i ) = i = 1 1 x k i 1 x i = 1 ϕ ( x ) i = 1 ( 1 x k i ) = p ( x ) ϕ ( x k ) p_k(x)=\prod_{i=1}^{\infty}(1+x^i+x^{2i}+...+x^{(k-1)i})\\ =\prod_{i=1}^{\infty}\frac{1-x^{ki}}{1-x^i}\\ =\frac 1 {\phi(x)}\prod_{i=1}^{\infty}(1-x^{ki})\\ =p(x)\phi(x^k)

由五邊形數定理,有:
p k ( x ) = p ( x ) ( 1 + i = 1 ( 1 ) i ( x k 3 i 2 + i 2 + x k 3 i 2 i 2 ) p_k(x)=p(x)(1+\sum_{i=1}^{\infty}(-1)^i(x^{k\frac {3i^2+i}2}+x^{k\frac {3i^2-i}2})
f ( n ) f(n) 表示對於 n n 沒有限制的劃分計數, f k ( n ) f_k(n) 表示對於 n n 的限制 k k 的劃分計數,有:
f k ( n ) = f ( n ) + i = 1 ( 1 ) i ( f ( n k 3 i 2 + i 2 ) + f ( n k 3 i 2 i 2 ) ) f_k(n)=f(n)+\sum_{i=1}(-1)^i(f(n-k\frac{3i^2+i}2)+f(n-k\frac {3i^2-i}2))
O ( n n ) O(n\sqrt n) 預處理出 f ( n ) f(n) ,就可以 O ( n ) O(\sqrt n) 計算 f k f_k 了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cstdio>
#include<random>
using namespace std;
//--Container
//--
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
const ll md=1e9+7;
ll qs[100010];
void _init(){
    int i,j,k,a,b;for(qs[0]=1,i=1;i<=100000;++i){
        for(j=k=1;;++j,k*=-1){
            a=(3*(ll)j*j+j)>>1,b=(3*(ll)j*j-j)>>1;
            if(i<b)break;qs[i]=(qs[i]+md+qs[i-b]*k)%md;
            if(i<a)break;qs[i]=(qs[i]+md+qs[i-a]*k)%md;
        }
    }
};
ll _cl(int n,int dk){
    ll rs=qs[n];int i,j,k;ll a,b;for(j=1,k=-1;;++j,k*=-1){
        a=(3*(ll)j*j+j)>>1,b=(3*(ll)j*j-j)>>1;a*=dk,b*=dk;
        if(n<b)break;rs=(rs+md+qs[n-b]*k)%md;
        if(n<a)break;rs=(rs+md+qs[n-a]*k)%md;
    }
    return rs;
};
void cl(){
    int n,k;scanf("%d %d",&n,&k);printf("%lld\n",_cl(n,k));
};

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif // ONLINE_JUDGE
    int t;scanf("%d",&t);for(_init();t--;cl());
    return 0;
};