比赛 |
2022级数学专题练习赛9 |
评测结果 |
AAAAAAAAAAAAAAAWETEW |
题目名称 |
兔农 |
最终得分 |
75 |
用户昵称 |
yrtiop |
运行时间 |
5.819 s |
代码语言 |
C++ |
内存使用 |
103.05 MiB |
提交时间 |
2023-02-08 20:17:42 |
显示代码纯文本
// Problem: P2020 [NOI2011] 兔农
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2020
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
using i64 = long long;
const int N = 6e6;
i64 n,f[N + 5],k,p,m,a[N + 5],T;
bool flag[N + 5];
struct matrix {
i64 g[3][3];
matrix() {
memset(g , 0 , sizeof(g));
}
void clear() {
memset(g , 0 , sizeof(g));
return ;
}
void init() {
g[0][0] = g[1][1] = g[2][2] = 1;
return ;
}
matrix operator * (const matrix& z)const {
matrix c;
for(int k = 0;k < 3;++ k)
for(int i = 0;i < 3;++ i)
for(int j = 0;j < 3;++ j)
(c.g[i][j] += g[i][k] * z.g[k][j] % p) %= p;
return c;
}
}F,G,P,pac;
matrix power(matrix x,i64 y) {
matrix ans;
ans.init();
for(;y;y >>= 1) {
if(y & 1)
ans = ans * x;
x = x * x;
}
return ans;
}
int main() {
freopen("noi2011_rabbit.in","r",stdin);
freopen("noi2011_rabbit.out","w",stdout);
scanf("%lld %lld %lld",&n,&k,&p);
std::vector<i64> tags;
f[1] = f[2] = 1;
for(int i = 3;i <= N;++ i) {
f[i] = (f[i - 1] + f[i - 2]) % k;
if(f[i] == 1) {
flag[i] = true;
tags.pb(i);
f[i] = 0;
}
}
f[1] = f[2] = 1;
for(int i = 3;i <= N;++ i) {
f[i] = (f[i - 1] + f[i - 2]) % p;
if(flag[i])
(f[i] += p - 1) %= p;
}
if(n <= (i64)N) {
printf("%lld\n",f[n]);
return 0;
}
G.g[0][0] = 1;
G.g[1][0] = 1;
G.g[0][1] = 1;
G.g[2][2] = 1;
P = G;
P.g[2][0] = p - 1;
F.g[0][0] = f[tags[0]];
F.g[0][1] = f[tags[0] - 1];
F.g[0][2] = 1;
m = tags.size();
for(int i = 1;i < m;++ i)
a[i] = tags[i] - tags[i - 1];
i64 len = 0;
for(T = 1;T <= 10;++ T) {
bool flag = true;
for(int i = 1;i < m - T&&i <= 1000;++ i) {
if(a[i] != a[i + T]) {
flag = false;
break ;
}
}
if(flag) {
pac.init();
for(int i = 1;i <= T;++ i) {
pac = pac * power(G , a[i] - 1);
pac = pac * P;
len += a[i];
}
break ;
}
}
pac = power(pac , (n - tags[0]) / len);
F = F * pac;
i64 res = n - tags[0] - ((n - tags[0]) / len) * len;
for(int i = 1;i <= T;++ i) {
if(res <= 0)
break ;
F = F * power(G , std::min(res , a[i] - 1));
res -= a[i] - 1;
if(res <= 0)
break ;
F = F * P;
-- res;
}
printf("%lld\n",F.g[0][0]);
return 0;
}