• [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;
    }
    
    
  • 相关阅读:
    Ubuntu 12.04和MySQL5.5安装
    ORACLE DBA 常用命令
    ORACLE 常见错误及解决方法集锦
    oracle中imp命令详解
    iframe自适应高度 兼容所有
    Linux Oracle 11g dataguard物理standby的配置
    LINUX 常用命令
    【CF】【Dijkstra】E. Buy and Delete
    【网络流】对于拆点的一点思考
    【PTA】最小堆
  • 原文地址:https://www.cnblogs.com/mollnn/p/13215996.html
Copyright © 2020-2023  润新知