首页 > 代码库 > (2016弱校联盟十一专场10.5) F. Fibonacci of Fibonacci

(2016弱校联盟十一专场10.5) F. Fibonacci of Fibonacci

题目链接

技术分享

 

题目大意就是这个,先找出下标的循环节,再快速幂对20160519取余就行了。

找出下标循环节:

 

#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
    int i=1,a=0,b=1;
    for(;;i++)
    {
        int t=b;
        b=(a+b)%20160519;
        a=t%20160519;
        if(a==0&&b==1)
        {
            printf("%d\n",i);
            break;
        }
    }
    return 0;
}

 

AC代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include <string.h>
using namespace std;
typedef long long ll;
const ll mod=20160519;
const ll mod2=26880696;
int n,t;
ll ans_id,ans_x;
struct matrix
{
    ll data[2][2];//必须ll
};
matrix I={1,0,1,1};//起始!
matrix a={1,1,1,0};//乘数!
matrix multi(matrix a,matrix b,ll mod)
{
    matrix c;
    memset(c.data,0,sizeof(c.data));
    for(int i=0;i<2;i++)
    for(int j=0;j<2;j++)
    for(int k=0;k<2;k++)
    {
        c.data[i][j]=c.data[i][j]+(a.data[i][k]%mod)*(b.data[k][j]%mod); //超过ll
        c.data[i][j]%=mod;
    }
    return c;
}
long long pow(matrix a,int b,ll mod)
{
    matrix ans=I;
    while(b)
    {
        if(b&1)
        {
            ans=multi(ans,a,mod);
            b--;
        }
        b>>=1;
        a=multi(a,a,mod);
    }
    return ans.data[0][0];
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        ans_id=pow(a,n-1,mod2);
        ans_x=pow(a,ans_id-1,mod);
        printf("%lld\n",ans_x);
    }
    return 0;
}

 

(2016弱校联盟十一专场10.5) F. Fibonacci of Fibonacci