0%

Codeforces Round #140 (Div. 1) C. Anniversary

通过这个题目发现了一个很奇妙的性质 \[gcd(fib(a),fib(b))=fib(gcd(a,b))\] 这样只需要枚举下标的公因数,然后看看有没有\(k\)个符合条件就可以了。 注意,因为是通过\(\frac{r}{p}-\frac{l-1}{p}\)判断的。而本质不同的\(\frac{r}{p}\)只有\(\sqrt{r}\)级别,所以只需要枚举\(\sqrt{r}\)次即可,枚举\(\frac{r}{p}\)相同的最大的\(p\)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
LL m,a,b,k;
struct oo{
LL t[2][2];
};
oo su;
oo tt;
oo cheng(oo x,oo y)
{
oo ans;
for(int i=0;i<=1;i++)
{
for(int j=0;j<=1;j++)
{
ans.t[i][j]=0;
for(int k=0;k<=1;k++)
{
ans.t[i][j]+=x.t[i][k]*y.t[k][j];
ans.t[i][j]%=m;
}
}
}
return ans;
}
oo kpow(LL x)
{
if(x==0) return su;
oo ans=kpow(x/2);
ans=cheng(ans,ans);
if(x%2) ans=cheng(ans,tt);
return ans;
}
LL ff(LL x)
{
su.t[0][1]=0;
su.t[0][0]=1;
su.t[1][0]=0;
su.t[1][1]=1;
tt.t[0][0]=0;
tt.t[0][1]=1;
tt.t[1][0]=1;
tt.t[1][1]=1;
if(x==1) return 1%m;
oo p=kpow(x-2);
//cout<<p.t[0][0]<<" "<<p.t[0][1]<<" "<<p.t[1][0]<<" "<<p.t[1][1]<<endl;
LL ans=p.t[0][1]+p.t[1][1];
ans%=m;
return ans;
}
int main()
{
scanf("%I64d%I64d%I64d%I64d",&m,&b,&a,&k);
LL ans=0,pos;
pos=a/k;
while(pos>=1)
{
LL pp=a/pos-(b-1)/pos;
if(pp>=k) ans=max(pos,ans);
pos=a/(a/pos+1);
}
//cout<<ans<<endl;
printf("%I64d",ff(ans));
return 0;
}