1. 题目

传送门= ̄ω ̄=

2. 题解

居然比赛的时候想出来正解了。

设广义斐波那契数列:$A$,第$i$项为$A_i$

设“狭义”(一般)斐波那契:$Fib$,第$i$项为$Fib_i$

则:$A_i=A_1\times Fib_{i-2}+A_2\times Fib_{i-1}$

那么题目要求:$A_k=m(MOD\ p)$

即:$A_1\times Fib_{k-2}+A_2\times Fib_{k-1}=m(MOD\ p)$

其中$A_1,k,m,p$均已知,只有$A_2$未知。

设$G=A_1\times Fib_{k-2}$

则:$G+A_2\times Fib_{k-1}=m(MOD\ p)$

$A_2\times Fib_{k-1}=m-G(MOD\ p)$

显然这就是个线性同余方程了,求出最小整数解然后求解的个数即可。

其中计算$Fib_{k-1},Fib_{k-2}$可以$O(log_2k)$的复杂度求出。

总复杂度$O(T\times log_2k)$

求斐波那契数列我没用矩阵乘法,用了这个:传送门= ̄ω ̄=,可以去参考一下~

代码(有点凌乱):

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<typename _Tp>inline void IN(_Tp&dig)
{
    char c;bool flag=0;dig=0;
    while(c=getchar(),!isdigit(c))if(c=='-')flag=1;
    while(isdigit(c))dig=dig*10+c-'0',c=getchar();
    if(flag)dig=-dig;
}
LL cur,pre,MOD,T,G,X,Y,t;
void dfs(LL a)
{
    if(a==1){pre=0,cur=1;return;}
    if(a==2){pre=cur=1;return;}
    if(a&1){dfs(a-1),swap(pre,cur),cur=(pre+cur)%MOD;return;}
    dfs(a>>1);
    LL tem=cur;
    cur=(cur*cur%MOD+((cur*pre%MOD)<<1)%MOD)%MOD;
    pre=(tem*tem%MOD+pre*pre%MOD)%MOD;
}
LL exgcd(LL a,LL b,LL&x,LL&y)
{
    if(!b){x=1,y=0;return a;}
    int tmp=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return tmp;
}
int main()
{
    IN(T);
    begin:while(T--)
    {
        LL a,l,r,k,m,F1,F2;
        IN(a),IN(l),IN(r),IN(k),IN(MOD),IN(m);
        if(k==1)
        {
            if(a%MOD==m)puts("1");
            else puts("0");
            goto begin;
        }
        if(k==2)
        {
            printf("%lld\n",((l-1)/MOD)-(r/MOD));
            goto begin;
        }
        a%=MOD,dfs(k-1),F1=pre,F2=cur;
        m=((m-(F1*a)%MOD)%MOD+MOD)%MOD;
        G=exgcd(F2,MOD,X,Y);
        if(m%G){puts("0");goto begin;}
        t=MOD/G,X=((X*m/G)%t+t)%t;
        if(X>r){puts("0");goto begin;}
        r-=X;
        if(X>l)l=0;else l-=X;
        printf("%lld\n",((r+t)/t)-((l+t-1)/t));
    }
    return 0;
}
分类: 文章

XZYQvQ

炒鸡辣鸡的制杖蒟蒻一枚QvQ

发表评论

电子邮件地址不会被公开。 必填项已用*标注

你是机器人吗? =。= *