题目描述
“codeplus比赛的时候在做什么?有没有空?能来解决丢番图方程问题吗?”sublinekelzrip这样问qmqmqm。
当然,qmqmqm并不会丢番图方程问题,所以sublinekelzrip改为提出了另一个题目,现在请你帮助qmqmqm解决这个题目。
这个问题是这样的:
若一个数列aaa满足条件an=an−1+an−2,n≥3a_n=a_{n-1}+a_{n-2},n \geq 3a
n
=a
n−1
+a
n−2
,n≥3,而a1,a2a_1,a_2a
1
,a
2
为任意实数,则我们称这个数列为广义斐波那契数列。
现在请你求出满足条件a1=ia_1=ia
1
=i,a2a_2a
2
为区间[l,r][l,r][l,r]中的整数,且
a
k
mod
p
m
的广义斐波那契数列有多少个。
输入格式
从标准输入读入数据。
本题包含多组数据,输入第一行包含一个正整数TTT,表示数据组数。对于每组数据:
一行六个用空格隔开的整数i,l,r,k,p,mi,l,r,k,p,mi,l,r,k,p,m,意义如「题目描述」所示。
输出格式
输出到标准输出。
输出共TTT行,每行一个数表示该组数据的答案。
样例
样例输入
6
2 17 68 3 23 1
1 17 68 3 57 1
5 17 68 10 11 9
5 17 68 10 71 9
10 17 68 11 12 3
10 17 68 8 6 4
样例输出
3
1
4
1
5
9
数据范围与提示
测试点 kkk rrr 其他
1 ≤100\leq 100≤100 ≤100\leq 100≤100 无
2 ≤105\leq 10^5≤10
5
≤105\leq 10^5≤10
5
3
4 ≤1018\leq 10^{18}≤10
18
5
6 ≤105\leq 10^5≤10
5
≤1018\leq 10^{18}≤10
18
ppp为质数
7
8 ≤ 1018\leq 10^{18}≤10
18
9 无
10
对于所有数据,0≤l≤r0 \leq l \leq r0≤l≤r,1≤p≤1091 \leq p \leq 10^91≤p≤10
9
,0≤m< p0 \leq m < p0≤m< p,T=10T=10T=10,0≤i≤10180 \leq i \leq 10^{18}0≤i≤10
18
,k≥3k \geq 3k≥3。
来自 CodePlus 2017 12 月赛,清华大学计算机科学与技术系学生算法与竞赛协会 荣誉出品。
Credit:idea/卢政荣 命题/卢政荣 验题/吕时清,茹逸中,王聿中
Git Repo:https://git.thusaac.org/publish/CodePlus201712
感谢腾讯公司对此次比赛的支持。
题解
第k项(ai+bx,l<=x<=r)的系数a,b,是斐波那契数列中的两项,可以通过矩阵求得。
然后就是解同余方程。
代码
#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll a[3][3],b[3][3];
ll x,l,r,k,p,m,y;
void mul(ll a[3][3],ll b[3][3],ll c[3][3])
{
ll tmp[3][3];
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
{
tmp[i][j]=0;
for (int k=1;k<=2;k++)
(tmp[i][j]+=a[i][k]*b[k][j]%p)%=p;
}
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
c[i][j]=tmp[i][j];
}
ll get(ll k)
{
if (k==-2) return 1;
if (k==-1) return 0;
if (k==0) return 1;
b[1][1]=b[2][2]=1;b[1][2]=b[2][1]=0;
a[1][1]=1;a[1][2]=1;a[2][1]=1;a[2][2]=0;
while (k)
{
if (k&1) mul(a,b,b);
mul(a,a,a);
k>>=1;
}
return b[1][1];
}
ll exgcd(ll a,ll b)
{
if (b==0){x=1;y=0;return a;}
ll d=exgcd(b,a%b);
ll t=x;
x=y;y=t-a/b*y;
return d;
}
void solve()
{
scanf("%lld%lld%lld%lld%lld%lld",&x,&l,&r,&k,&p,&m);x%=p;
ll i=get(k-3),A=get(k-2);
i=i*x%p;i=((m-i)%p+p)%p;
ll d=exgcd(A,p);
if (i%d){puts("0");return;}
x=x*i/d;ll q=p/d;
x=x+(l-x)/q*q;
if (x<l) x+=q;
if (x>r) puts("0");else printf("%lld\n",(r-x)/q+1);
}
int main()
{
int Case=read();
while (Case--) solve();
return 0;
}