[P4451] [国家集训队] 整数的lqp拆分

Description

定义斐波那契数 (F_1=1,F_2=1,F_n=F_{n-1}+F_{n-2}),整数的 lqp 拆分是满足任意 (m>0)(a_1 ,a_2 ,a_3…a_m>0),且 (a_1+a_2+a_3+…+a_m=n) 的一个有序集合。定义这个拆分的权值 (F_{a_1}F_{a_2}…F_{a_m}),对于所有的拆分,权值之和 (sumprod_{i=1}^m F_{a_i}) 是多少?

Solution

推导 Fib 数列的生成函数

(A=1+x+2x^2+3x^3+5x^4+...)

于是有

(xA=x+x^2+2x^3+3x^4+5x^5)

(x^2A=x^2+x^3+2x^4+3x^5+5x^6)

做差得

[A=frac 1 {1-x-x^2} ]

本题中由于整体右移了一位,修正为

[A=frac x {1-x-x^2} ]

于是答案为

[G=sum_{i=0}^infty A^i=frac 1 {1-F}=frac {1-x-x^2}{1-2x-x^2}=1+frac {x}{1-2x-x^2} ]

考虑到 (1-2x-x^2=(1-(1+sqrt 2)x)(1-(1-sqrt 2)x))

解得 (x_1=-sqrt 2 +1, x_2 = sqrt 2 +1)

于是,设 (g_n = c_1(-sqrt 2 +1)^n + c_2 (sqrt 2 +1)^n)

利用 (n=0,1) 定出

[c_1 = frac {sqrt 2 -1}{2sqrt 2} , quad c_2 = frac {sqrt 2 + 1}{2 sqrt 2} ]

于是暴力用二次剩余算出各项的值,然后快速幂即可,注意把 (n) 模上 (mod-1)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 1e9+7;

int qpow(int p,int q)
{
    return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;
}
int inv(int p)
{
    return qpow(p,mod-2);
}

namespace cipolla
{
inline int le(int x)
{
    return qpow(x,(mod-1)/2);
}
int w;
struct comp
{
    int x,y;
    comp(int a=0,int b=0)
    {
        x=a;
        y=b;
    }
};
comp operator + (comp a,comp b)
{
    return comp((a.x+b.x)%mod,(a.y+b.y)%mod);
}
comp operator - (comp a,comp b)
{
    return comp((a.x-b.x+mod)%mod,(a.y-b.y+mod)%mod);
}
comp operator * (comp a,comp b)
{
    return comp((a.x*b.x+a.y*b.y%mod*w)%mod,(a.x*b.y+a.y*b.x)%mod);
}
comp operator ^ (comp a,int b)
{
    comp o(1,0);
    for(; b; a=a*a,b>>=1) if(b&1) o=o*a;
    return o;
}
int calc(int x)
{
    x%=mod;
    int a;
    while(true)
    {
        a=rand();
        w=(a*a-x+mod)%mod;
        if(le(w)==mod-1) break;
    }
    comp s=comp(a,1)^((mod+1)/2);
    return min(s.x,mod-s.x);
}
}

int n;

signed main()
{
    ios::sync_with_stdio(false);
    string s;
    cin>>s;
    for(int i=0;i<s.length();i++)
    {
        int t=s[i]-'0';
        n=(n*10+t)%(mod-1);
    }
    int sq2=cipolla::calc(2),sp2=sq2;
    int c1=(sq2-1)*inv(2*sp2%mod)%mod, c2=(sq2+1)*inv(2*sp2%mod)%mod;
    int x1=(-sq2+1+mod)%mod, x2=(sq2+1)%mod; 
    cout<<(c1*qpow(x1,n-1)+c2*(qpow(x2,n-1)))%mod<<endl;
}

原文地址:https://www.cnblogs.com/mollnn/p/13215996.html