• P5091 【模板】扩展欧拉定理


    题目链接

    昨天考试考到了欧拉公式,结果发现自己不会,就来恶补一下。

    欧拉公式

    • (a^b mod p = a^{b}) (b < varphi(p))
    • (a^b mod p = a^{bmod varphi(p) + varphi(p)}) $b geq varphi(p) $

    具体证明的话可以看一下 扶咕咕的博客,我也是看他的博客才懂得QWQ。

    在预处理的的时候,我们就可以判断一下 (b) 的大小,具体的话可以这么来实现

    LL get(int p)
    {
    	bool flag = 0;//flag 表示当前读入的这个数是否大于p
    	LL s = 0, w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9')
    	{
    		s = s * 10 + ch - '0';
    		if(s >= p) flag = 1;s %= p;//如果大于p的话,就把flag变为1,同时在对p取模
    		ch = getchar();
    	}
    	if(flag) s += p;//根据欧拉定理如果指数大于p,则需要再加上一个p
    	return s * w;
    }
    

    处理一个数的欧拉函数可以在 (sqrt n) 的时间内求出来,根据他的递推公式 (displaystylevarphi(n) = n prod_{质数pmid n}(1-{1over p})) 求一下就行

    代码

    LL Euler(LL n)
    {
    	LL res = n;
    	for(int i = 2; i <= sqrt(n); i++)//枚举他的约数
    	{
    		if(n % i == 0)
    		{
    			res = res / i * (i-1);//递推公式
    			while(n % i == 0) n /= i;//这个质因子除尽
    		}
    	}
    	if(n > 1) res = res / n * (n-1);//最后剩下的质因子可能会大于 n,比如 6 = 2 * 3,这时候再把这个质因子算上就行
    	return res;
    }
    

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define LL long long
    LL a,m,b,p;
    LL get(int p)
    {
    	bool flag = 0;
    	LL s = 0, w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9')
    	{
    		s = s * 10 + ch - '0';
    		if(s >= p)
    		{
    			flag = 1;
    			s %= p;
    		}
    		ch = getchar();
    	}
    	if(flag) s += p;
    	return s * w;
    }
    LL ksm(LL a,LL b,LL p)
    {
    	LL res = 1;
    	for(; b; b >>= 1)
    	{
    		if(b & 1) res = res * a % p;
    		a = a * a % p;
    	}
    	return res;
    }
    LL Euler(LL n)
    {
    	LL res = n;
    	for(int i = 2; i <= sqrt(n); i++)
    	{
    		if(n % i == 0)
    		{
    			res = res / i * (i-1);
    			while(n % i == 0) n /= i;
    		}
    	}
    	if(n > 1) res = res / n * (n-1);
    	return res;
    }
    int main()
    {
    	scanf("%lld%lld",&a,&m); p = Euler(m); b = get(p);
    	printf("%lld
    ",ksm(a,b,m) % m);
    	return 0;
    }
    
  • 相关阅读:
    支持向量机(SVM)相关免费学习视频集锦
    《量化投资:以MATLAB为工具》连载(2)基础篇-N分钟学会MATLAB(中)
    《量化投资:以MATLAB为工具》连载(1)基础篇-N分钟学会MATLAB(上)
    OpenCV 轮廓基本特征
    !!破解灯塔线取点与画线的“难点”
    理工科应该的知道的C/C++数学计算库(转)
    521. 最长特殊序列 Ⅰ
    520. 检测大写字母
    459. 重复的子字符串
    443. 压缩字符串
  • 原文地址:https://www.cnblogs.com/genshy/p/13716089.html
Copyright © 2020-2023  润新知