码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-12-24 13:42:07      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:int   operator   main   name   clu   get   gif   结果   cstring   

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

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

  斐波那契数列满足$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)

标签:int   operator   main   name   clu   get   gif   结果   cstring   

原文地址:http://www.cnblogs.com/Sakits/p/8097744.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!