【洛谷P5091】【模板】欧拉定理【扩展欧拉定理】

本文介绍如何使用扩展欧拉定理解决幂模运算问题,通过模板题解析,详细阐述了算法思路和代码实现,适用于处理大规模数据的幂次方模运算。

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

题目大意:

题目链接:https://www.luogu.org/problem/P5091
a b m o d    m a^b\mod m abmodm


思路:

扩展欧拉定理的模板题。
具体还不会证明。证明就出门右转题解区吧。
欧拉定理:对于任意的 a , p ∈ Z ∗ a,p\in \Z^* a,pZ,若满足 ( a , b ) = 1 (a,b)=1 (a,b)=1,那么必然就有 a φ ( m ) ≡ 1 ( m o d   p ) a^{\varphi(m)} \equiv 1(mod\ p) aφ(m)1(mod p)
扩展欧拉定理:当 p ≥ φ ( m ) p\geq \varphi(m) pφ(m)时,必有
a p ≡ a p   m o d   φ ( m ) + φ ( m ) ( m o d   p ) a^p\equiv a^{p\ mod\ \varphi(m)+\varphi(m)}(mod\ p) apap mod φ(m)+φ(m)(mod p)
所以就算出 φ ( p ) \varphi(p) φ(p),然后从高位到低位依次读入 b b b的每一位,同时取模 φ ( m ) \varphi(m) φ(m)。然后由于最终的指数不会超过 1 0 6 10^6 106,所以直接暴力乘上去就可以了。
注意只有在 b > φ ( m ) b>\varphi(m) b>φ(m)时指数才需要在最后加 φ ( m ) \varphi(m) φ(m)


代码:

#include <cstdio>
using namespace std;
typedef long long ll;

ll a,b,p,q,phi;
bool flag;

int main()
{
	scanf("%lld%lld",&a,&p);
	phi=q=p;
	for (ll i=2;i*i<=q;i++)
		if (!(q%i))
		{
			phi=phi/i*(i-1);
			while (!(q%i)) q/=i;
		}
	if (q>1) phi=phi/q*(q-1);
	while (scanf("%1lld",&q)==1)
	{
		b=b*10+q;
		if (b>=phi) flag=1;
		b%=phi;
	}
	if (flag) b+=phi;
	for (ll i=1,x=a;i<b;i++)
		a=a*x%p;
	printf("%lld\n",a);
	return 0;
} 
### 关于洛谷平台上的回文质数问题 #### 使用欧拉筛法求解回文质数的思路 对于回文质数这一类问题,核心在于两个方面:一是如何高效地筛选出质数;二是怎样快速判定一个数是否为回文数。针对第一个需求,采用线性时间复杂度O(n)级别的欧拉筛算法可以显著提高效率[^1]。 具体来说,在构建埃氏筛的基础上改进而来,通过标记最小素因子来避免重复合数被多次处理的情况发生。当遇到一个新的未被访问过的整数值时,则将其加入到已知素数列表之中,并利用这些已经确认的小范围内的全部素因数去更新更大范围内可能存在的新合数状态。 至于第二个条件——验证回文特性,可以通过字符串反转比较的方式轻松完成。即先将待测正整数转换成字符形式,再检查该串与其逆序版本之间是否存在差异即可得出结论。 #### 代码实现 下面给出一段基于上述原理编写的C++程序: ```cpp #include <iostream> #include <vector> using namespace std; bool isPalindrome(int n){ string s=to_string(n); int l=s.length(); for (int i=0;i<l/2;++i) if(s[i]!=s[l-i-1])return false; return true; } const int MAXN = 1e7; // 定义最大检测界限 bitset<MAXN> notPrime; // 布尔数组记录非质数位置 vector<int> primes; // 动态数组存储找到的所有质数 void eulerSieve(){ notPrime[0]=notPrime[1]=true; for(long long i=2;i<=MAXN;i++){ if(!notPrime[i]){ primes.push_back(i); // 将当前索引作为新的质数保存起来 if(isPalindrome(i)) cout<<i<<" "; // 输出符合条件的回文质数 } for(size_t j=0;j<primes.size() && primes[j]*i<=MAXN ;j++){ notPrime[primes[j]*i]=true; if(i%primes[j]==0) break; } } } ``` 此段代码实现了对指定区间内所有满足既是质数又是回文性质的数据项进行查找并打印的功能。其中`isPalindrome()`辅助函数用于检验给定参数n所代表的具体数值是不是具有镜像对称特征;而主体部分则运用了优化后的欧拉筛技术来进行初步过滤工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值