1. 程式人生 > 實用技巧 >BZOJ-2173 整數的lqp拆分(生成函式)

BZOJ-2173 整數的lqp拆分(生成函式)

題目描述

  關於 \(n\) 的整數劃分的定義為滿足任意 \(m\geq 0,a_1,a_2,a_3,\cdots,a_m>0\),且 \(a_1+a_2+a_3+\cdots+a_m=n\) 的一個有序集合。

  對於每個整數劃分,定義這個劃分的權值為 \(F_{a_1}\times F_{a_2}\times \cdots\times F_{a_m}\)(其中 \(F_0=0,F_1=1,F_n=F_{n-1}+F_{n-2}(n>1)\))。給出數字 \(n(n\leq 10^6)\),對於所有的劃分,求它們的權值之和。

分析

  已知斐波那契數的生成函式為:

\[F(x)=\frac{x}{1-x-x^2} \]

  拆分成 \(m\) 個數時,答案的生成函式為 \(F^{m}(x)\)(相當於把方案數最終算在了對應項的係數上)。

  答案的生成函式為:

\[G(x)=\sum_{i=0}^{\infty}F^{i}(x)=\frac{1\times(1-F(x)^{\infty})}{1-F(x)}=\frac{1}{1-F(x)}=\frac{1-x-x^2}{1-2x-x^2}=1+\frac{x}{1-2x-x^2} \]

  化簡後面的分式:令 \(\frac{x}{1-2x-x^2}=A(\frac{1}{1-ax}-\frac{1}{1-bx})\)

  解得:\(A=\frac{\sqrt{2}}{4},a=1+\sqrt{2},b=1-\sqrt{2}\)

  即:

\[G(x)=1+\frac{\sqrt{2}}{4}\Big(\frac{1}{1-(1+\sqrt{2})x}-\frac{1}{1-(1-\sqrt{2})x}\Big) \]

  把 \(G(x)\) 的封閉形式轉化成形式冪級數形式,則 \(g(n)\) 就是答案。

\[G(x)=1+\frac{\sqrt{2}}{4}\sum_{i=1}^{\infty}\Big((1+\sqrt{2})^{i}-(1-\sqrt{2})^{i}\Big)x^i \]

  因此:

\[g(n)=\frac{\sqrt{2}}{4}\Big((1+\sqrt{2})^{n}-(1-\sqrt{2})^{n}\Big) \]

  根據二次剩餘:\(\sqrt{2}\equiv 59713600\pmod {10^9+7}\)

  答案為:

\[g(n)=59713600\times250000002\times[(1+59713600)^{n}-(1-59713600)^{n}]\pmod {10^9+7} \]

  \(n\) 非常大,尤拉降冪一下,則答案為:

\[g(n)=59713600\times250000002\times[(1+59713600)^{n\mod {10^9+6}}-(1-59713600)^{n\mod {10^9+6}}]\pmod {10^9+7} \]

程式碼

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
inline long long read()
{
    long long x=0,f=1;char ch=getchar();
    long long p=mod-1;
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=(x*10ll+ch-48)%p;ch=getchar();}
    return x*f;
}
long long quick_pow(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
    long long n=read();
    long long ans1=1ll*59713600*250000002%mod;
    long long ans2=(quick_pow(59713601,n)-quick_pow(940286408,n)+mod)%mod;
    printf("%lld\n",ans1*ans2%mod);
    return 0;
}