🍑 算法题解专栏
🙈 好事多磨,一口吃不成胖子
🍑 关键点:数据范围过大
🍑 推导过程
🍑 矩阵乘法
👨🏫 参考题解
🍑 java代码实现
import java.util.Scanner;
public class Main
{
static long n, m, p;
// 龟速乘法(快速积)
static long qmul(long a, long b)
{
long res = 0;
while (b != 0)
{
if ((b & 1) == 1)
{
res = (res + a) % p;
}
a = (a + a) % p;
b >>= 1;
}
return res;
}
// 矩阵乘法
static void mul(long[][] a, long[][] b)
{
// 临时矩阵暂存结果
long[][] tmp = new long[2][2];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
tmp[i][j] = (tmp[i][j] + qmul(a[i][k], b[k][j])) % p;
// 拷贝
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
a[i][j] = tmp[i][j];
}
// 计算斐波那契数列的第 n 项
static long F(long n)
{
// 极端情况
if (n == 0)
return 0;
// 根据fn来进行构造矩阵
// fn,分别为f(1) f(2)
long[][] f = { { 1, 1 }, { 0, 0 } };
// 累乘矩阵
long[][] a = { { 0, 1 }, { 1, 1 } };
// 快速幂
for (long k = n - 1; k != 0; k >>= 1)
{
if ((k & 1) == 1)
mul(f, a);
mul(a, a);
}
return f[0][0];
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
while (sc.hasNext())
{
n = sc.nextLong();
m = sc.nextLong();
p = sc.nextLong();
System.out.println((G(n + 2, m) % p + p) % p);
}
}
// (F(m - 1) * F(n % m) - 1) mod F(m)
// (F(m - 1) * F(k) - 1) mod F(m)
static long H(long m, long k)
{
if (k % 2 == 1)
return F(m - k) - 1;
else
{
if (k == 0 || m == 2 && m - k == 1)
return F(m) - 1;
else
{
return F(m) - F(m - k) - 1;
}
}
}
static long G(long n, long m)
{
// 情况1:m为偶数
if (m % 2 == 0)
{
// n/m是偶数 f(n mod m)
if (n / m % 2 == 0)
{
// 特判情况
if (n % m == 0)
return F(m) - 1;
else
return F(n % m) - 1;
} else
{
// n/m为奇数 f(n mod m) * f(m-1)
return H(m, n % m);
}
} else
{ // 情况2:m为奇数
// n/m为偶数,n/2m为偶数 f(n mod m)
if (n / m % 2 == 0 && n / (2 * m) % 2 == 0)
{
// 特判
if (n % m == 0)
return F(m) - 1;
else
return F(n % m) - 1;
} else if (n / m % 2 == 0 && n / (2 * m) % 2 == 1) // n/m为偶数,n/2m为奇数 f(m) - f(n mod m)
{
// 特判f(m) - f(n mod m)为0情况 当f(m) == f(n % m),即m=2,n%m=1时
// f(m) - f(n mod m) = 0时
if (m == 2 && n % m == 1)
return F(m) - 1;
else
return F(m) - F(n % m) - 1;
} else if (n / m % 2 == 1 && n / (2 * m) % 2 == 0) // n/m为奇数,n/2m为偶数 f(m - 1) * f(n mod m)
{
return H(m, n % m);
} else
{
// n/m为奇数,n/2m为奇数 f(m) - f(m - 1) * f(n mod m)
// n mod m为奇数
if (n % m % 2 == 1)
{
if (m == 2 && m - n % m == 1)
return F(m) - 1;
else
return F(m) - F(m - n % m) - 1;
} else
{
// n mod m为偶数
// 判断f(m - n mod m)是否为0
return F(m - n % m) - 1;
}
}
}
}
}