数论(二次剩余 + 二项式定理 + 斐波那契数列) - Fibonacci Sum - HDU 6755

数论(二次剩余 + 二项式定理 + 斐波那契数列) - Fibonacci Sum - HDU 6755

2020 Multi-University Training Contest 1 1005

题意:

斐波那契数列:

{ F 0 = 0 , F 1 = 1 F n = F n 1 + F n 2 ( n > 1 ) \begin{cases}F_0=0,F_1=1\\\\F_n=F_{n-1}+F_{n-2}(n>1)\end{cases}

N C K 给定正整数N、C、K,计算:

( F 0 ) K + ( F C ) K + ( F 2 C ) K + . . . + ( F N C ) K (F_0)^K+(F_{C})^K+(F_{2C})^K+...+(F_{NC})^K

1 0 9 + 9 答案对10^9+9取模。

Input

The first line contains an integer T (1≤T≤200), denoting the number of test cases. Each test case contains three space separated integers in the order: N, C, K (1≤N,C≤1018,1≤K≤105).

Output

For each test case, output a single line containing the answer.

Sample Input

2
5 1 1
2 1 2

Sample Output

12
2

分析:

本题或许改编自: Power of Fibonacci - ZOJ 3774

斐波那契数列的通项公式:

F n = 1 5 [ ( 1 + 5 2 ) n ( 1 5 2 ) n ] F_n=\frac{1}{\sqrt{5}}[(\frac{1+\sqrt{5}}{2})^n-(\frac{1-\sqrt{5}}{2})^n]

5 1 0 9 首先,5是模数10^9的 二次剩余

x 2 5   m o d   1 0 9 + 9   x   5   m o d   1 0 9 + 9 即用满足:x^2≡5\ mod\ 10^9+9\ 的x来代替\ \sqrt{5}\ mod\ 10^9+9。

x = 383008016 计算得到一个满足条件的x=383008016

则: 1 5 276601605   ( m o d   1 0 9 + 9 ) , 1 + 5 2 691504013   ( m o d   1 0 9 + 9 ) , 1 5 2 308495997   ( m o d   1 0 9 + 9 ) \frac{1}{\sqrt{5}}≡276601605\ (mod\ 10^9+9),\frac{1+\sqrt{5}}{2}≡691504013\ (mod\ 10^9+9),\frac{1-\sqrt{5}}{2}≡308495997\ (mod\ 10^9+9)

D = 276601605 a = 691504013 b = 308495997 令D=276601605,a=691504013,b=308495997,

原式等价于对数列:

F n k = D k ( a n b n ) k F_n^k=D^k(a^n-b^n)^k

1 0 9 的部分项求和并对10^9取模。

( a n b n ) k 观察(a^n-b^n)^k,根据二项式展开:

( a n b n ) k = C k 0 ( a n ) k ( b n ) 0 ( 1 ) 0 + C k 1 ( a n ) k 1 ( b n ) 1 ( 1 ) 1 + . . . + C k r ( a n ) k r ( b n ) r ( 1 ) r + . . . + C k k ( a n ) 0 ( b n ) k ( 1 ) k (a^n-b^n)^k=C_k^0(a^n)^k(b^n)^0(-1)^0+C_k^1(a^n)^{k-1}(b^n)^1(-1)^1+...+C_k^r(a^n)^{k-r}(b^n)^r(-1)^r+...+C_k^k(a^n)^0(b^n)^k(-1)^k

( 1 ) r C k r = M r S n r = ( a n ) k r ( b n ) r 记(-1)^rC_k^r=M_r,S_{nr}=(a^{n})^{k-r}(b^{n})^r,上式转化为:

( a n b n ) k = M 0 S n 0 + M 1 S n 1 + . . . + M r S n r + . . . + M k S n k (a^n-b^n)^k=M_0S_{n0}+M_1S_{n1}+...+M_rS_{nr}+...+M_kS_{nk}

: 则:

F n k = D k ( M 0 S n 0 + M 1 S n 1 + . . . + M k S n k ) F_{n}^k=D^k(M_0S_{n0}+M_1S_{n1}+...+M_kS_{nk})

n S n r M r 不论n取何值,S_{nr}前的系数均相同,为M_r,

原式等价于:

( F 0 ) k + ( F C ) k + ( F 2 C ) k + . . . + ( F N C ) k = ( F C ) k + ( F 2 C ) k + . . . + ( F N C ) k (F_0)^k+(F_{C})^k+(F_{2C})^k+...+(F_{NC})^k=(F_{C})^k+(F_{2C})^k+...+(F_{NC})^k

= M 0 ( i = 1 N S ( i C ) 0 ) + M 1 ( i = 1 N S ( i C ) 1 ) + . . . + M k ( i = 1 N S ( i C ) k ) =M_0(\sum_{i=1}^NS_{(i·C)0})+M_1(\sum_{i=1}^NS_{(i·C)1})+...+M_k(\sum_{i=1}^NS_{(i·C)k})

k 1 0 5 0 k r r S i i 本题k≤10^5,可以从0到k枚举r,而当r为常数时,S_i是一个关于i的等比数列,

  q = S i + 1 S i = ( a i + 1 ) k r ( b i + 1 ) r ( a i ) k r ( b i ) r = a ( k r ) b r 公比\ q=\frac{S_{i+1}}{S_{i}}=\frac{(a^{i+1})^{k-r}(b^{i+1})^r}{(a^{i})^{k-r}(b^{i})^r}=a^{(k-r)}b^{r}

G i = S C i Q = q C = a C ( k r ) b C r G 1 = S C = a C ( k r ) b C r = Q 则数列G_i=S_{Ci}的公比为Q=q^C=a^{C(k-r)}b^{Cr},首项为G_1=S_{C}=a^{C(k-r)}b^{Cr}=Q

G i i = 1 N G i = Q ( Q n 1 ) Q 1 等比数列G_i求和:\sum_{i=1}^NG_i=\frac{Q(Q^n-1)}{Q-1}

r M r ( i = 1 N G i ) 因此,我们可以通过枚举r对M_r(\sum_{i=1}^NG_i)求和,即计算:

r = 0 k M r ( i = 1 N G i ) = r = 0 k ( 1 ) r C k r ( Q ( Q n 1 ) Q 1 ) Q = a C ( k r ) b C r \sum_{r=0}^kM_r(\sum_{i=1}^NG_i)=\sum_{r=0}^k(-1)^rC_k^r(\frac{Q(Q^n-1)}{Q-1}),其中Q=a^{C(k-r)}b^{Cr}。

注意:

Q = 1 i = 1 N G i = N ( 1 ) r C k r × N Q=1时,\sum_{i=1}^NG_i=N,直接累加(-1)^rC_k^r×N即可。

具体细节:

C r k C k r = k ! r ! ( k r ) ! k ! ①、求组合数C_r^k可以通过定义,C_k^r=\frac{k!}{r!·(k-r)!}来解决,需要预处理k!和对应的逆元。

a b r Q ②、将a、b带入,对枚举的每一个r,用快速幂求具体的Q。

优化:

本题时间限制卡的非常紧,需要对一些计算做优化:

  • 观察相邻两项的公比:

Q = a C ( k r ) b C r     \qquad Q=a^{C(k-r)}b^{Cr}\qquad\qquad\ \ \ ①

Q = a C ( k ( r + 1 ) ) b C ( r + 1 ) \qquad Q=a^{C(k-(r+1))}b^{C(r+1)}\qquad②

× ( b C a C ) = \qquad发现,①×-(\frac{b^C}{a^C})=②

\qquad因此,我们可以通过递归由①推②,减少快速幂的计算。

  • p = 1 0 9 + 9 a p 1 1 ( m o d   p ) 费马小定理:模数p=10^9+9是质数,可以通过费马小定理a^{p-1}≡1(mod\ p),优化快速幂。

时间复杂度: O ( T k l o g ( m o d ) ) . O(Tklog(mod)).


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define ll long long

using namespace std;

const int N=1e5, mod=1e9+9;
const int a=691504013, b=308495997, D=276601605;

int fac[N+10],inv[N+10];

int quick_pow(ll a,ll b,int mod)
{
    int res=1;
    a%=mod;
    while(b)
    {
        if(b&1) res=(ll)res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

void Init()
{
    fac[0]=1;
    for(int i=1;i<=N;i++) fac[i]=(ll)fac[i-1]*i%mod;
    for(int i=0;i<=N;i++) inv[i]=quick_pow(fac[i],mod-2,mod);
}

int INV(int x)
{
    return quick_pow(x,mod-2,mod);
}

int C(int n,int m)
{
    if(n<m) return 0;
    return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
} 

int Sum(ll n,ll c,int k)
{
    ll ans=0;
    int ac=quick_pow(a,c%(mod-1),mod),  //费马小定理
        bc=quick_pow(b,c%(mod-1),mod);
    int an=quick_pow(ac,k,mod), //an初始值为a^ck
        bn=1;   //bn初始值为b^0
    int ainv=INV(ac);   //a^c逆元
    
    for(int r=0;r<=k;r++)
    {
        int Q=(ll)an*bn%mod, S;
        
        int Ckr=C(k,r);
        if(r&1) Ckr=-Ckr;
        
        if(Q==1) S=n%mod;
        else S=(ll)Q*(quick_pow(Q,n%(mod-1),mod)-1)%mod*INV(Q-1)%mod;
        S=(ll)Ckr*S%mod;

        ans+=S;
        an=(ll)an*ainv%mod;
        bn=(ll)bn*bc%mod;
    }
    
    ans=(ans%mod+mod)*quick_pow(D,k,mod)%mod;
        
    return ans;
}

int main()
{
    Init();

    int T,k;
    ll n,c;
    cin>>T;
    while(T--)
    {
        scanf("%lld%lld%d",&n,&c,&k);
        printf("%d\n",Sum(n,c,k));
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/njuptACMcxk/article/details/107500765