USTCOJ 1239 God Created The Integers

本文介绍了如何解决USTCOJ 1239题,涉及二次剩余、拓展欧几里得算法以及高斯函数性质。计算与4k+1型质数p相关的Sp,并模p取逆,通过配对求和与高斯求和公式简化计算,最终求得结果并讨论了求模逆的优化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是我的第一篇博客,现在正在努力学习编程语言中,以此记录学习心得。

题目链接:http://acm.ustc.edu.cn/ustcoj/problem.php?id=1239;

题目大意是要求计算一个与p有关Sp,然后模p后取逆即结果。
                             

其中p是4k+1型质数p > 10。

这题我们需要以下知识,原理。(主要是二次剩余)

1,-1是4k+1型质数的二次剩余。(利用欧拉判别法(-1)^ ((p - 1)/ 2)= 1, 所以是二次剩余), 所以如果i是二次剩余,p - i

也是二次剩余。

2, 利用拓展欧几里得算法求逆。

3,1^2 + 2^2 + ......+n^2 = (2n + 1)(n + 1)n / 6.

我们记 ri 为 i * i (mod p)的值

由于高斯函数性质[i*i / p] = i * i / p - ri / p;

所以Sp = (1^2 + 2^2 + ......+((p - 1) / 2)^2) / p - (r1 + r2 + ...... + r(p - 1)/ 2) / p.

(我们把i 与 p - i 配对,和为p, 有(p - 1) / 4 对)

= ((p - 1)/ 2) * ((p + 1)/ 2) * p / 6 - ((p - 1)/ 4)* p / p

= p * (p – 1) / 24 + (p - 1)/ 4

= (p - 1)(p - 5)/ 24;

所以我们已经求得Sp的值,可以看出Sp (mod p) = 5 / 24;此处 5 / 24为连分数 .则Sp关于p的逆为 24 / 5.我们求5 的逆再乘以24即结果。于是只需要调用一次eEuclid(5, p),得倒5的系数。但是这个欧几里得算法只给出一个满足5 * x + p * y = gcd(5,p) = 1的解不保证在p的最小非负完系中,所以最后乘以24后再处理一下即可。

Euclid算法中,我用一个结构体保存结果,注意用long long类型避免过程中两个需要的系数超范围。其他数据类型用int更适合计算机运行。

代码如下:

 

#include<stdio.h>

struct Euclid
{
		int d;
		long long x, y;
};

 Euclid eEuclid(int p, int q)
{
		Euclid eu;

		if (q == 0)
		{
				eu.d = p;
				eu.x = 1;
				eu.y = 0;
				return eu;
		}
		else
		{
				eu.d = eEuclid(q, p % q).d;
				eu.x = eEuclid(q, p % q).y;
				eu.y = eEuclid(q, p % q).x - (p / q) * eEuclid(q, p % q).y;	
				return eu;
		}	
}

int main()
{
		int k = 1, t, re, p;

		scanf("%d", &t);
		while (t--)
		{
				scanf("%d", &p);
				re = 24 * eEuclid(5, p).x % p;
				if (re < 0)
						re += p;
				printf("Case #%d: %d\n", k++, re);
		}

		return 0;
}


总结:

感觉这个代码并非最优,应当有更快的求模逆的算法,OJ上也看到了0ms通过的大牛, 这个代码用了8ms,还是需要不断学习完善自己。加油!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值