• 「CodePlus 2017 12 月赛」可做题2(矩阵快速幂+exgcd+二分)


      昨天这题死活调不出来结果是一个地方没取模,凉凉。

      首先有个一眼就能看出来的规律...

      斐波那契数列满足$a_1, a_2, a_1+a_2, a_1+2a_2, 2a_1+3a_2, 3a_1+5a_2$

      也就是第k项是$fib(k-2)*a_1+fib(k-1)*a_2$

      问题就转化成了求$(fib(k-2)*a_1+fib(k-1)*a_2)\% p=m$,$a_2$在$[l,r]$上的个数。

      显然$fib(k-2)a_1$是个常数,那一看就是exgcd题了。。。

      令$a=fib(k-1),b=p,c=(m-fib(k-2)*a_1\% p+p)\% p$

      然后就变成了求$ax+by=c$,$x$在$[l,r]$上有几个解。

      先求出最小正整数解,然后二分一下就完了。

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define int long long
    using namespace std;
    const int maxn=500010, inf=1e9;
    int n, a1, l, r, K, p, m, T, mod, x, y;
    struct mtx {int mp[2][2];mtx(){memset(mp, 0, sizeof(mp));}}base, ans;
    inline void read(int &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;    
    } 
    mtx operator*(mtx a, mtx b)
    {
        mtx c;
        for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
        for(int k=0;k<2;k++)
        c.mp[i][j]=(c.mp[i][j]+a.mp[i][k]*b.mp[k][j])%p;
        return c;
    }
    void power(int b)
    {
        for(;b;b>>=1, base=base*base)
        if(b&1) ans=ans*base;
    }
    int exgcd(int a, int b, int &x, int &y)
    {
        if(!b) return x=1, y=0, a;
        int ans=exgcd(b, a%b, x, y);
        int tmp=x; x=y; y=tmp-a/b*y;
        return ans;
    }
    inline ll find(int x, int up)
    {
        int l=0, r=up/p+1;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(x+p*mid>=up) r=mid;
            else l=mid+1;
        }
        return l;
    }
    #undef int
    int main()
    {
        read(T);
        while(T--)
        {
            base.mp[0][0]=base.mp[0][1]=base.mp[1][0]=1; base.mp[1][1]=0;
            ans.mp[1][1]=ans.mp[0][0]=1; ans.mp[1][0]=ans.mp[0][1]=0;
            read(a1); read(l); read(r); read(K); read(p); read(m); a1%=p;
            power(K-2); mod=(m-a1*ans.mp[1][0]%p+p)%p;
            int d=exgcd(ans.mp[0][0], p, x, y);
            if(mod%d!=0) {puts("0"); continue;}
            x=x*(mod/d); p/=d; x=(x%p+p)%p;
            printf("%lld
    ", find(x, r+1)-find(x, l));
        }
    }
    View Code
  • 相关阅读:
    计算最大公因数
    最大子序列和问题
    C++三大函数:析构函数、复制构造函数和operator=
    C++函数返回值传递
    C++动态内存分配
    Halcon Assistants
    网格细分算法
    HDevelop Guide
    MeshLab
    point cloud registration
  • 原文地址:https://www.cnblogs.com/Sakits/p/8097744.html
Copyright © 2020-2023  润新知