题意翻译
设
是斐波那契数列,在
中选
个数
,使得
尽可能大,
输出对
取模后的结果。
样例输入输出:
题解:from 洛谷
首先我们考虑斐波那契数列
的一个性质:
然后只要找到最大的
使得
的倍数在
里大于或者等于
个即可.
猜猜这个
能不能二分?
我竟然对不能二分的东西写了二分,而且一开始以为自己二分萎了后
来才发现根本不能二分,调了5个小时!(
在
中的倍数个数不会随着
![]()
增大而增多)。
根据数据范围我们用
的枚举. 假设存在一个数字
,对于
来说,它在[
内的倍数
的个数变化了,这样的
存在
个.由于我们要求的只是最大值,我们只需要对于
之
内的每一个i判断ii和r/i的倍数在
是不是大于或者等于
个即可.这样可以求出
,答案
就是第
个斐波那契数,用矩阵快速幂即可.
代码实现:
#include<iostream>
#include<cstring>
#include<cmath>
#include<stack>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e5+100;
LL f[2],arr[2][2],mod;
void mul(LL f[2],LL a[2][2]){
LL c[2];
memset(c,0,sizeof(c));
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
c[i]=(c[i]+f[j]*a[i][j]%mod)%mod;
}
}
memcpy(f,c,sizeof(c));
}
void mulself(LL a[2][2]){
LL c[2][2];
memset(c,0,sizeof(c));
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
c[i][j]=(c[i][j]+a[i][k]*a[k][j]%mod)%mod;
}
}
}
memcpy(a,c,sizeof(c));
}
bool judge(LL x,LL l,LL r,LL k){
return (r/x-(l-1)/x)>=k;
}
int main(){
LL l,r,k,n,tmp;
while(cin>>mod>>l>>r>>k){
n=0;
//这里不能用二分,不满足单调性
for(LL i=1;i*i<=r;i++){
if(judge(i,l,r,k)){
n=max(n,i);
}
if(r/i!=i&&judge(r/i,l,r,k)){
n=max(n,r/i);
}
}
//求斐波那契数列第 N 项
f[0]=0,f[1]=1;
arr[0][0]=0,arr[0][1]=1,arr[1][0]=1,arr[1][1]=1;
while(n){
if(n&1)mul(f,arr);
mulself(arr);
n>>=1;
}
cout<<f[0]<<endl;
}
return 0;
}
THE END;