数列(循环节)
题意
有一个整数数列
该数列的前两项的具体值已知,其它项可以通过如下递推式求出:
给定一个可能非常大的正整数和两个不太大的正整数,请你分别计算并输出对取模的值。
题目链接:https://www.acwing.com/problem/content/4584/
数据范围
思路
首先我们观察到的范围较小,只有,因此数列中的数最多有个取值。
特别大,这种题目的典型套路是分析循环节。
那么什么时候才会出现循环呢?如果和在之前出现过,即存在满足并且。那么就出现循环了。其中循环节的长度为。
因此,我们只需要计算出位于循环节的哪个位置即可,即:。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e7 + 10, M = 3010;
int a[N], p, q;
int m, k;
int id[M][M];
string n;
int main()
{
cin >> a[0] >> a[1] >> p >> q >> m >> k >> n;
a[0] %= m, a[1] %= m;
id[a[0]][a[1]] = 1;
int ed, st;
for(int i = 2; i < N; i ++) {
a[i] = (a[i - 1] * p % m + a[i - 2] * q % m) % m;
}
for(int i = 2; i < N; i ++) {
if(id[a[i - 1]][a[i]]) {
ed = i - 2;
st = id[a[i - 1]][a[i]] - 1;
break;
}
id[a[i - 1]][a[i]] = i;
}
int len = ed - st + 1;
if(n.size() <= 7) {
int num = 0;
for(int i = 0; i < n.size(); i ++) {
num = num * 10 + n[i] - '0';
}
for(int i = 1; i <= k; i ++) {
cout << a[num + i] << '\n';
}
}
else {
int num = 0;
for(int i = 0; i < n.size(); i ++) {
num = (num * 10 % len + n[i] - '0') % len;
}
int r = (num - st % len + len) % len;
for(int i = st + r + 1; i <= st + r + k; i ++) {
cout << a[i] << '\n';
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!