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

Posted Sakits

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「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\n", find(x, r+1)-find(x, l));
    }
}
View Code

以上是关于「CodePlus 2017 12 月赛」可做题2(矩阵快速幂+exgcd)的主要内容,如果未能解决你的问题,请参考以下文章

「CodePlus 2017 11 月赛」可做题

CodePlus2017 12月月赛 div2可做题2

bzoj5108 [CodePlus2017]可做题 位运算dp+离散

bzoj5108[CodePlus2017]可做题 拆位+乱搞

「CodePlus 2017 12 月赛」白金元首与独舞

「CodePlus 2017 12 月赛」火锅盛宴