bzoj2432: [Noi2011]兔农 快速幂+数论

不难发现,这个题就是求斐波那契数列改化,由于有一个很强的结论,斐波那契数列取模是一个周期数列,所以我们可以去找循环节,然后找到循环节后把这第一个循环节处理出来。 其实vfk说的很详细了,注意这里mod的数不一定是个质数,我们只能用拓展欧几里得求逆元。。。。

http://vfleaking.blog.163.com/blog/static/174807634201341721051604/

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define oo 2000000000000000000000LL
#define ll long long
#define maxn 1000100
ll n,len[maxn],next[maxn];
int inv[maxn],k,mod;
void init()
{
    inv[1]=1;
    for(int i=2;i=k) fib[i]-=k;
        if(pos[fib[i]]==-1) pos[fib[i]]=i;
    }
}
struct matrix
{
    int a[3][3];
    void cl()
    {
        memset(a,0,sizeof(a));
    }
    void one()
    {
        memset(a,0,sizeof(a));
        for(int i=0;i<3;i++) a[i][i]=1;
    }
    void A()
    {
        a[0][0]=1;a[0][1]=1;a[0][2]=0;
        a[1][0]=1;a[1][1]=0;a[1][2]=0;
        a[2][0]=0;a[2][1]=0;a[2][2]=1;
    }
    void B()
    {
        a[0][0]=1;a[0][1]=1;a[0][2]=0;
        a[1][0]=1;a[1][1]=0;a[1][2]=0;
        a[2][0]=mod-1;a[2][1]=0;a[2][2]=1;
    }
};
matrix operator *(matrix aa,matrix bb)
{
    ll a[3][3];
    for(int i=0;i<3;i++)
    for(int j=0;j<3;j++)
    {
        a[i][j]=0;
        for(int k=0;k<3;k++)
        {
            a[i][j]+=(ll)aa.a[i][k]*bb.a[k][j]%mod;
            a[i][j]%=mod;
        }
    }
 
    matrix cc;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        {
            cc.a[i][j]=a[i][j];
        }
    return cc;
}
matrix matpow(matrix x,ll y)
{
    matrix res;res.one();
    while(y)
    {
        if(y&1){
            res=res*x;
        }
        x=x*x;
        y>>=1;
    }
    return res;
}
int vis[maxn];
int main()
{
    //freopen("rabbit20.in","r",stdin);
    scanf("%lld%d%d",&n,&k,&mod);
    for(int i=1;i0)
    {
        int cur = cirs;
        ll totL = 0;
        matrix matC;matC.one();
        do
        {
            matC = matC*matpow(AA,len[cur]-1);
            matC = matC*BB;
            totL += len[cur];
            cur = next[cur];
        }
        while (cur != cirs);
        use=use*matpow(matC, n / totL);
        n=n%totL;
        for(int i=cirs;;i=next[i])
        {
            if(n


你可能感兴趣的:(dp,数论)