[2018.07.31 T1] 第一题

暂无连接

第一题

【问题描述】

斐波那契数列满足 f[0]=0,f[1]=1,f[i]=f[i1]+f[i2](i>=2) f [ 0 ] = 0 , f [ 1 ] = 1 , f [ i ] = f [ i − 1 ] + f [ i − 2 ] ( i >= 2 ) 。已知 f[i] f [ i ] 1013 10 13 取模的结果 k k ,求最小的可能的 i。无解输出 1 − 1

【输入格式】

输入包含一个非负整数 k k

【输出格式】

输出一个整数,为最小的可能的 i。无解输出 1 − 1

【输入样例 1】

17711

【输出样例 1】

22

【输入样例 2】

7

【输出样例 2】

9366795780274

【数据范围】

前三个数据点的 k k 分别为 201807129982443531000000007

对于 100% 100 % 的数据点, 0<=k<1013 0 <= k < 10 13

题解

又双叕TM是打表找规律。。。

当然你可以去找网上的证明。

话说这个部分分真TM不良心,直接 O(n) O ( n ) 推,考试结束都没出来。。。

打个大表,你会发现 mod 10 m o d   10 的循环节是 60 60 mod 100 m o d   100 300 300 mod 1000 m o d   1000 1500 1500 mod 10n m o d   10 n 1.5×10n 1.5 × 10 n 。下一层循环节是上一层的因数,而且循环节大小是线性的,所以我们可以一位一位的满足 k k

在跳循环节的时候,我们还需要验证当前项是否满足要求,需要矩阵加速递推数列,而且mod 1013还需要慢速乘,真是恶心。

代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e13;
ll loop[15],k;
struct matrix{ll sq[3][3];matrix(){memset(sq,0,sizeof(sq));}}mat,one;
vector<ll>yeah[15];
ll X(ll x,ll p){ll ans=0;for(;p;p>>=1,(x<<=1)%=mod)if(p&1)(ans+=x)%=mod;return ans;}
matrix operator *(matrix a,matrix b)
{
    matrix c;
    c.sq[1][1]=(X(a.sq[1][1],b.sq[1][1])+X(a.sq[1][2],b.sq[2][1]))%mod;
    c.sq[1][2]=(X(a.sq[1][1],b.sq[1][2])+X(a.sq[1][2],b.sq[2][2]))%mod;
    c.sq[2][1]=(X(a.sq[2][1],b.sq[1][1])+X(a.sq[2][2],b.sq[2][1]))%mod;
    c.sq[2][2]=(X(a.sq[2][1],b.sq[1][2])+X(a.sq[2][2],b.sq[2][2]))%mod;
    return c;
}
matrix power(matrix x,ll p){matrix ans=one;for(;p;p>>=1,x=x*x)if(p&1)ans=ans*x;return ans;}
void in(){scanf("%lld",&k);}
void ac()
{
    int a;ll mod=10,pos,now,ans=LONG_LONG_MAX;bool flag=0;
    one.sq[1][1]=one.sq[2][2]=1;
    mat.sq[1][1]=mat.sq[1][2]=mat.sq[2][1]=1;
    loop[0]=1,loop[1]=60,loop[2]=300;
    yeah[0].push_back(1);
    for(ll i=3,x=1500;i<=13;++i,x*=10)loop[i]=x;
    for(int p=1;p<=13;++p,mod*=10,flag=0)
    {
        for(int i=yeah[p-1].size()-1;i>=0;--i)
        {
            pos=yeah[p-1][i];
            for(ll j=0;j<loop[p];j+=loop[p-1])
            {now=power(mat,pos+j-1).sq[1][1];if(now%mod==k%mod){flag=1;yeah[p].push_back(pos+j);}}
        }
        if(!flag)puts("-1"),exit(0);
    }
    for(int i=yeah[13].size()-1;i>=0;--i)ans=min(ans,yeah[13][i]);
    printf("%lld",ans);
}
int main(){in();ac();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值