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

壹、题目描述 ¶

传送门 to Luogu.

贰、题解 ¶

考虑到每种拆分的不同贡献,设 \(f(n)\)​ 表示拆分 \(n\)​ 的贡献,那么

\[f(n)=\sum_{i=0}^nfib(i)\times f(n-i) \\ F(x)=\sum_{n=0}^\infty\sum_{i=0}^n fib(i)f(n-i)x^n \\ F(x)=\sum_{i=0}^\infty fib(i)x^i\times \sum_{j=0}^\infty f(j)x^j \\ F(x)=G(x)F(x)+1 \\ F(x)={1\over 1-{x\over 1-x-x^2}}={1+{x\over 1-2x-x^2}} \\ \]

注意不要漏掉常数项 \(1\).

那么有

\[F(x)=1+{1\over 2\sqrt 2}\left({1\over 1-(1+\sqrt 2)x}-{1\over 1-(1-\sqrt 2)x}\right) \\ F(x)=1+\sum_i{1\over 2\sqrt 2}\left((1+\sqrt 2)^i-(1-\sqrt 2)^i \right)x^i \\ [x^n]F(x)={(1+\sqrt 2)^n-(1-\sqrt 2)^n\over 2\sqrt 2} \pmod p \]

\(2\)\(\bmod 10^9+7\) 下的二次剩余为 \(59713600\)​.

同时,\(n\) 在指数上,可以考虑使用欧拉定理降次,从而总复杂度为 \(\mathcal O(\log_{10}n)\)(因为你要读入

叁、参考代码 ¶

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;

#define NDUBUG
#include<cassert>

namespace Elaina{
    #define rep(i, l, r) for(int i=(l), i##_end_=(r); i<=i##_end_; ++i)
    #define drep(i, l, r) for(int i=(l), i##_end_=(r); i>=i##_end_; --i)
    #define fi first
    #define se second
    #define mp(a, b) make_pair(a, b)
    #define Endl putchar('\n')
    #define mmset(a, b) memset(a, b, sizeof a)
    // #define int long long
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    template<class T>inline T fab(T x){ return x<0? -x: x; }
    template<class T>inline void getmin(T& x, const T rhs){ x=min(x, rhs); }
    template<class T>inline void getmax(T& x, const T rhs){ x=max(x, rhs); }
    template<class T>inline T readin(T x){
        x=0; int f=0; char c;
        while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
        for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
        return f? -x: x;
    }
    template<class T>inline void writc(T x, char s='\n'){
        static int fwri_sta[1005], fwri_ed=0;
        if(x<0) putchar('-'), x=-x;
        do fwri_sta[++fwri_ed]=x%10, x/=10; while(x);
        while(putchar(fwri_sta[fwri_ed--]^48), fwri_ed);
        putchar(s);
    }
}
using namespace Elaina;

const int Mod=1e9+7;
const int phiMod=Mod-1;
const int sqrt2=59713600;
const int maxl=1e4;

inline int qkpow(int a, int n){
    int ret=1;
    for(; n>0; n>>=1, a=1ll*a*a%Mod)
        if(n&1) ret=1ll*ret*a%Mod;
    return ret;
}

char s[maxl+5];
int len, n;

signed main(){
    scanf("%s", s); len=strlen(s);
    for(int i=0; i<len; ++i)
        n=(10ll*n+(s[i]^48))%phiMod;
    writc(1ll*(qkpow(1+sqrt2, n)+Mod-qkpow(1+Mod-sqrt2, n))*qkpow(2ll*sqrt2%Mod, Mod-2)%Mod);
    return 0;
}
posted @ 2021-07-27 12:07  Arextre  阅读(107)  评论(0编辑  收藏  举报