( 数论专题 )【 斐波那契通项公式 + 等比数列求和公式 】

( 数论专题 )【 斐波那契通项公式 + 等比数列求和公式 】

斐波那契通项公式( 证明略 ):

 

 

例题:

求当n趋向于无穷大,Sn等于什么,输出最简分数。

分子是斐波那契数列,分母是K的 i 次方, K是给定的。

 

思路:

代码:

#include <bits/stdc++.h>
#define int long long

using namespace std;

signed main()
{
    int T;cin>>T;
    while ( T-- ) {
        int k;cin>>k;
        int up=k,down=k*k-k-1;
        int gcd = __gcd(up,down);
        up/=gcd;down/=gcd;
        if ( down==1 ) cout << up << endl;
        else cout << up << "/" << down << endl;
    }

    return 0;
}

2020 Multi-University Training Contest 1

Fibonacci Sum

将斐波那契的通项公式带入需要求的式子,再根据二项式定理展开

这样就根据等比公式就可以得到通式,枚举i=0~k相加就是答案。

还有一个问题是a和b不是整数,所以没法在乘法中取模。

这就需要用到二项同余求解

求得x = 383008016, 因为x也可以等于\sqrt{5}所以\sqrt{5}在%mod的条件下也可以等于383008016

( 这里提一句,比赛时写二项同余代码太费时间,可以直接暴力求,lst = [ i for i in range(1,mod) if i*i%mod==5 ] , 不到一分钟就能跑出来,类比到其他的情况也可以 )

A = (1+x)*inv(2)%mod          B = (1-x)*inv(2)%mod+mod

注意:等比公式可能出现分母为0的情况,显然会出错,需要特判。

注意:需要优化,否则超时。

化简出来的和等于

ans=\sum ^{i=0,i<=k} (-1)^{i} * C_{k}^{i} * ( \frac{tmp*(tmp^{n}-1)}{tmp-1} )

tmp=(A^{c})^{k-i}*(B^{c})^{i}

观察随着 i 的变化tmp的变化,容易发现 i 增加 1 tmp乘以B除以A。

所以就省去了很多个快速幂,直接手动维护tmp的值就可以了。

代码:

#include<bits/stdc++.h>
#define int long long

using namespace std;
const int mod = 1000000009;
int a[100005],b[100005];

int qpow( int a, int n )
{
    int re = 1;
    while ( n ) {
        if ( n&1 ) re=(re*a)%mod;
        a=(a*a)%mod;
        n>>=1;
    }
    return re;
}

int C( int n, int m )
{
    if ( n<m ) return 0;
    int ans = ((a[n]*b[m])%mod*b[n-m])%mod;
    return ans;
}

int inv( int x )
{
    return qpow(x,mod-2);
}

signed main()
{
//    cout << qpow(3,128900) << endl;
//    cout << qpow(3,128900%mod) << endl;
    // x^2 = 5%(1e9+9)
//    int x = 383008016;
//    cout << (1+x)*inv(2)%mod << endl;
//    cout << (1-x)*inv(2)%mod+mod << endl;
    int A=691504013,B=308495997;
    a[0]=a[1]=1;
    for ( int i=2; i<=100003; i++ ) a[i]=(a[i-1]*i)%mod;
    for ( int i=0; i<=100003; i++ ) b[i]=qpow(a[i],mod-2);

    int n,c,k,T;cin>>T;
    while ( T-- ) {
        scanf("%lld %lld %lld",&n,&c,&k);
        int ac = qpow(A,c);
        int bc = qpow(B,c);
        int bei = bc*inv(ac)%mod;
        int Bei = qpow(bei,n);
        int tmp = qpow(ac,k);
        int Tmp = qpow(tmp,n);

        int sum = 0,now;
        for ( int i=0; i<=k; i++ ) {
            if ( tmp==1 ) now = C(k,i)*(n%mod)%mod;
            else now = C(k,i)*tmp%mod*(Tmp-1)%mod*inv(tmp-1)%mod;
            if ( i%2==0 ) sum = (sum+now)%mod;
            else {
                sum = (sum-now)%mod;
                if ( sum<0 ) sum+=mod;
            }
            tmp = tmp*bei%mod;
            Tmp = Tmp*Bei%mod;
        }
        sum *= inv( qpow(383008016,k) );
        sum %= mod;
        if ( sum<0 ) sum+=mod;
        printf("%lld\n",sum);
    }

    return 0;
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值