?还 TLE ?
查看原帖
?还 TLE ?
747401
dfs0ms楼主2023/1/31 16:15

没错又是我,我的上一个帖子在这里: ?TLE?

这次我写了 BSGSBSGS,理论上来说复杂度是保持在 O(sqrt(n))O(sqrt(n)) 不变的,但是我超时了,蒟蒻求助大佬帮忙看一下为什么啊 QAQ

代码:

/*
斐波那契数列的循环节的上界为 6p
设斐波那契的第 i 项和第 i + 1 项构成的矩阵为 Ai,转移矩阵为B。
如果有循环节 k,那么有 A1 * B ^ k = A1 mod p
B ^ k = I,I 表示单位矩阵,将问题转化为 BSGS 的标准形式

B ^ k = I,设 k = i * s - j,s = ceil(sqrt(mod)),i, j <= s
B ^ (i * s - j) = I
B ^ (i * s) = B ^ j
枚举 j,O(sqrt(mod)),映射 M[B ^ j] = j
枚举 i,O(sqrt(mod)),如果 M[B ^ (i * s)] != 0,循环节 = i * s - j
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <unordered_map>
#include <map>
#define int long long
using namespace std;
void write(__int128 x)
{
	if(x<0)
	{
		putchar('-');
		x=-x;
	}
	if(x<10)
	{
		putchar(x+48);
		return;
	}
	write(x/10);
	putchar(x%10+48);
}
const int N = 30000010;

struct gjd
{
	int a[N], cnt;
	void scan()
	{
		char c;
		while (scanf("%c", &c) && ('0' <= c && c <= '9')) { a[++cnt] = c - '0'; }
		for (int i = 1; i <= cnt / 2; i++) swap(a[i], a[cnt - i + 1]);
	}
	int div(int x) /// 返回 a % x
	{
		for (int i = cnt; i >= 2; i--) { a[i - 1] += (a[i] % x) * 10; a[i] /= x; }
		return a[1] % x;
	}
} n;
int mod;

struct matrix
{
	int a[4][4];
	void clear() { memset(a, 0, sizeof(a)); }
	void fil(matrix* b)
	{
		clear();
		for (int i = 1; i <= 2; i++)
			for (int j = 1; j <= 2; j++) a[i][j] = b->a[i][j];
	}
	void mul(matrix* b)
	{
		int tmp[4][4]; memset(tmp, 0, sizeof(tmp));
		for (int i = 1; i <= 2; i++)
			for (int j = 1; j <= 2; j++)
				for (int k = 1; k <= 2; k++)
				{
					tmp[i][j] += a[i][k] * b->a[k][j];
					tmp[i][j] %= mod;
				}
		for (int i = 1; i <= 2; i++)
			for (int j = 1; j <= 2; j++) a[i][j] = tmp[i][j];
	}
	void pow(matrix* b, int p) /// a = b ^ p
	{
		memset(a, 0, sizeof(a)); a[1][1] = a[2][2] = 1;
		matrix base; base.fil(b);
		while (p)
		{
			if (p & 1) mul(&base);
			matrix tmp; tmp.fil(&base); base.mul(&tmp); p >>= 1;
		}
	}
	__int128 tranverse()
	{
		__int128 ret = 0, base = 1e10;
    /// 对于 a[][],如果 a[][] = base,a[1][2] = a[2][1],压缩时减去一维
		ret = ret * base + (__int128) a[1][1];
		ret = ret * base + (__int128) a[2][1];
		ret = ret * base + (__int128) a[2][2];
		return ret;
	}
	void print()
	{
	    for (int i = 1; i <= 2; i++)
	    {
			for (int j = 1; j <= 2; j++) printf("%lld ", a[i][j]);
			printf("\n");
	    }
	}
} base, I; /// 转移矩阵 (在 BSGS 函数中不改变),单位矩阵

int get(int x) /// 获取 f[x]
{
	matrix ret; ret.fil(&I); ret.pow(&base, x - 1);
	return (ret.a[1][1] + ret.a[2][1]) % mod;
}

map<__int128, int> M; /// mp[k] 表示矩阵为 k 的 j = 多少
int s; /// i * s - j
int len; /// 循环节长度

void BSGS()
{
	M[I.tranverse()] = 0; /// j = 0,j 可以 = 0,i 不行
	matrix tmp; tmp.fil(&I); /// M[tmp]
	for (int j = 1; j < s; j++) /// M[base ^ j] = j,j 不能 = s
	{
		tmp.mul(&base);
		M[tmp.tranverse()] = j;
	}
	
	tmp.fil(&I);
	matrix tmp2; tmp2.pow(&base, s); /// tmp2 = base ^ s
	for (int i = 1; i <= s; i++) /// M[base ^ (i * s)]
	{
		tmp.mul(&tmp2); int j = M[tmp.tranverse()];
		if (j != 0) { len = i * s - j; break; }
	}
}


signed main()
{
	n.scan(); scanf("%lld", &mod); s = ceil(sqrt(8 * mod)); /// 循环节上界是 6 * mod
	base.a[1][1] = 0; base.a[1][2] = 1;
	base.a[2][1] = 1; base.a[2][2] = 1;
	I.a[1][1] = 1; I.a[2][2] = 1;
	BSGS();
	int fn = n.div(len);
	int res = get(fn); printf("%lld", res);
	return 0;
}

得了 83 分捏

2023/1/31 16:15
加载中...