昨天这题死活调不出来结果是一个地方没取模,凉凉。
首先有个一眼就能看出来的规律...
斐波那契数列满足$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)); } }