超级数列

超级数列

总时间限制: 1000ms 内存限制: 65536kB

描述

数列 an的通项公式是 an+3= an+2+ an+1+ an(n > 0)

给定数列的 a1, a2, a3和 N (N < 1000000), 求 aN在 16进制中的后两位数字 (超过 9 的数字用A~F表示, 不足两位在前面补 0)

提示: 不能直接算出完整的 aN, 有些测试样例中 aN 超出 long long 能表示的范围

a1, a2, a3可以用 int 表示

输入

第一行是一个整数 T, 代表测试数据数量.
之后每行有4个数字, 分别是 a_1, a_2, a_3 和 N.

输出

输出有 T 行, 每行是对应测试点的 a_N 在 16 进制下的后两位

样例输入

4
1 1 1 10
1 1 1 11
1 2 3 5000
257 1 399 1234

样例输出

69
C1
04
A1

我的答案

#include
#include
#include
int a[1000000][3];
int main()
{
     
	int T;
	scanf("%d", &T);
	for (int q = 1; q <= T; q++)
	{
     
		int b[3], n;
		scanf("%d%d%d%d", &b[0], &b[1], &b[2], &n);
		for (int i = 0; i <= 2; i++)
		{
     
			int tmp = b[i];
			a[i][0] = tmp % 16;
			tmp /= 16;
			a[i][1] = tmp % 16;
		}
		if (n > 3)
		{
     
			for (int i = 3; i < n; i++)
			{
     
				int tmp = 0;
				for (int j = 1; j <= 3; j++)
				{
     
					tmp += a[i - j][0] + a[i - j][1] * 16;//把后三项的后两位全部加起来再除16取余得到新的后两位
				}
				a[i][0] = tmp % 16;
				tmp /= 16;
				a[i][1] = tmp % 16;
			}
		}
		if (a[n - 1][1] < 10)printf("%d", a[n - 1][1]);
		else printf("%c", 'A' + a[n - 1][1] - 10);

		if (a[n - 1][0] < 10)printf("%d", a[n - 1][0]);
		else printf("%c", 'A' + a[n - 1][0] - 10);
		printf("\n");
	}
	return 0;
}

标答

int main() {
     
	int i, m, n, t, a, b, c;
	scanf("%d", &t);
	while (t--) {
     
		scanf("%d%d%d%d", &a, &b, &c, &n);
		//n为1,2,3时特殊处理
		if (n == 1)
			c = a & 0xFF; //位运算,等价于a%256
		else if (n == 2)
			c = b & 0xFF;
		else if (n == 3)
			c = c & 0xFF;
		else {
     
			for (i = 3; i < n; i++) {
     
				m = ((a & 0xFF) + (b & 0xFF) + (c & 0xFF)) & 0xFF;//m=第i+1项
				a = b, b = c, c = m; //注意换位先后顺序
			}
		}
		printf("%X%X\n", (c >> 4), (c & 15)); //用%X输出大写16进制数
	}
	return 0;
}

相比标答,我的答案里面仍然残留着一些不够简洁和直接的东西:
1)相比最初的做法,我放弃了用字符串储存的想法,但是还是把最后两位数字分开存在了数组里面,然而这是不必要的;标答里面就是最后面再把后两位转换为两个十六进制下的数;
2)同时,也没有必要把从a4到an之间的每个结果都记录下来,只需要在循环中保留最近的三项的值就可以了。

但是无论是哪种方式,都需要意识到这道题得从小的项往大的走,而不能从n开始倒推(比如下面那样),不然就会溢出了。

//愚蠢的错误示范
int an(int x, int y, int z, int n)
{
     
	if (n == 1)return x;
	if (n == 2)return y;
	if (n == 3)return z;
	int o = an(x, y, z, n - 1);//这里是想用递归
	if (o > 1000)o %= 1000;
	int p = an(x, y, z, n - 2);
	if (p > 1000)p %= 1000;
	int q = an(x, y, z, n - 3);
	if (q > 1000)q %= 1000;
	int w = o + q + p;
	if (x > 1000)w %= 1000;
	return w;
}

害 每次做错题整理都要感慨一遍,我好蠢啊orz

你可能感兴趣的:(超级数列)