【自用】关于欧拉函数以及逆元的一些模板

求欧拉函数φ

O()√时间复杂度的算法

首先我们要求φ(x),可以先将其分解成∏(apii)的形式,其中a是素数。

然后可以推导出公式φ(x)=∏(apii?api?1i)

然后这个可以实现为φ(x)=x/∏(ai?1)

这样就可以在√时间内出解了。

线性时间复杂度的算法

线性筛!

因为欧拉函数是积性函数,所以我们可以采用线性筛。

过程见下方代码getphi()函数。

基于欧拉函数的求逆元

首先有欧拉公式 xφ(p)%p==1

所以x?xφ(p)?1%p==1

这样xφ(p)?1就是x在mod p 意义下的逆元。

O(log)时间复杂度求逆元

不考虑求φ,我们通过快速幂求逆元的时间复杂度是O(log)级别的

线性时间复杂度的算法

同样是线性筛,代码在下面。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
using namespace std;
int Phi(int x)
{
    int i,ans=x;
    for(i=2;i*i<=x;i++)if(x%i==0)
    {
        ans/=i,ans*=i-1;
        while(x%i==0)x/=i;
    }
    if(x>1)ans/=x,ans*=x-1;
    return ans;
}
int prime[N],phi[N],num;
bool vis[N];
void getphi(int n=1000000)
{
    int i,j,k;
    phi[1]=1;
    for(i=2;i<=n;i++)
    {
        if(!vis[i])prime[++num]=i,phi[i]=i-1;
        for(j=1;j<=num;j++)
        {
            k=i*prime[j];
            if(k>n)break;
            vis[k]=1;
            if(i%prime[j]==0)
            {
                phi[k]=phi[i]*prime[j];
                break;
            }
            phi[k]=phi[i]*(prime[j]-1);
        }
    }
    return ;
}
long long inv[N],p;
long long power(long long x,int k)
{
    long long ans=1;
    while(k)
    {
        if(k&1)ans=ans*x%p;
        x=x*x%p,k>>=1;
    }
    return ans;
}
long long Inv(long long x){return power(x,phi[p]-1);}
void getinv(int n=1000000)
{
    inv[1]=1;
    for(int i=2;i<=n;i++)
        inv[i]=(long long)(p-p/i)*inv[p%i]%p;
}
int main()
{
    scanf("%d",&p);
    getphi();
    getinv();
}
时间: 2024-10-13 10:05:12

【自用】关于欧拉函数以及逆元的一些模板的相关文章

清华集训 2014--奇数国(线段树&amp;欧拉函数&amp;乘法逆元&amp;状态压缩)

昨天想了一晚...早上AC了... 这么长时间没打线段树,这回居然一次过了... 感觉数论方面应该已经没有太大问题了... 之后要开始搞动态规划之类的东西了... 题意 在一片美丽的大陆上有100000个国家,记为1到100000.这里经济发达,有数不尽的账房,并且每个国家有一个银行.某大公司的领袖在这100000个银行开户时都存了3大洋,他惜财如命,因此会不时地派小弟GFS清点一些银行的存款或者让GFS改变某个银行的存款.该村子在财产上的求和运算等同于我们的乘法运算,也就是说领袖开户时的存款总

欧拉函数phi值的计算模板

求小于n且与n互质的整数的个数.告诉你n的唯一分解式 我们可以运用容斥原理,先分别减去是p1,p2,p3..pn的倍数,再加上同时是他们素因子的个数,再减去3个……以此类推即可. 我们可以化简一下公式:f(x)=x*(1-1/p1)*(1-1/p2).....,其中p1,p2.....是n的素因子. 这就是大名鼎鼎的欧拉函数,然后我们可以用编程轻松的解决这个问题 运用求质数的方法,每次找到一个素因子,然后将它除净,就可以保证找到的因子都是素数 #include<bits/stdc++.h> u

POJ 2478 欧拉函数(欧拉筛法) HDU 1576 逆元求法

相关逆元求法,我之前有写过,还有欧拉函数的求法,欧拉函数与逆元的关系  点击 POJ 2478 又是一个打表的题目,一眼看出结果就是前n个欧拉函数值的和. 这里直接计算欧拉函数值求和会超时,看见多组数据. 然后就是计算欧拉函数,打表就好了. #include <stdio.h> #include <string.h> #include <iostream> using namespace std; typedef long long LL; const int N =

欧拉函数(模板,相关问题持续更新中)

欧拉函数是一个很有用的东东.可以被扩展用来解决许多与素数相关的问题,逆元问题,欧拉函数降幂等! 概念:欧拉函数是小于或等于n的正整数中与n互质的数的数目(特别地φ(1)=1),若n为质数可直接根据性质得出,否则的话要求解. 求解模板: 1 int Euler(int n) 2 { 3 if(n==1) return 1; 4 int ans=n; 5 6 for(int i=2;i*i<=n;++i) 7 { 8 if(n%i==0) 9 { 10 while(n%i==0) n/=i; 11

O(n)求素数,求欧拉函数,求莫比乌斯函数,求对mod的逆元,各种求

筛素数 void shai() { no[1]=true;no[0]=true; for(int i=2;i<=r;i++) { if(!no[i]) p[++p[0]]=i; int j=1,t=i*p[1]; while(j<=p[0] && t<=r) { no[t]=true; if(i%p[j]==0) //每一个数字都有最小质因子.这里往后的数都会被筛过的,break break; t=i*p[++j]; } } } O(n)筛欧拉函数 void find()

BZOJ 3813 奇数国 欧拉函数+线段树+乘法逆元

题目大意:给出一个序列,支持修改操作,求这个序列连续一段的乘积的欧拉函数.每个数的最大质因子不超过281. 思路:φ(n) = n * (1 - 1 / p1) * (1 - 1 / p2) * (1 - 1 / p3) * (1 - 1 / p4)--*(1 - 1 / pn) = n  / (p1 * p2 * p3 * -- * pn) * ((p1 - 1) * (p2 - 1) * (p3 - 1) * -- * (pn - 1)) 于是这个东西只需要维护一下区间中的指数,用bitse

算法模板——单个值欧拉函数

输入N,输出phi(N) 这样的单个值欧拉函数程序一般见于部分数论题,以及有时候求逆元且取模的数不是质数的情况(逆元:A/B=A*Bphi(p)-1 (mod p),一般常见题中p是质数,phi(p)-1=p-2) (Tip:我是来水经验的不解释,不过话说真的好久没写这个了TT) 1 var i:int64; 2 function Eula(x:int64):int64; 3 var res:int64;i:longint; 4 begin 5 res:=x; 6 for i:=2 to tru

数论快速入门(同余、扩展欧几里德、中国剩余定理、大素数测定和整数分解、素数三种筛法、欧拉函数以及各种模板)

数学渣渣愉快的玩了一把数论,来总结一下几种常用的算法入门,不过鶸也是刚刚入门, 所以也只是粗略的记录下原理,贴下模板,以及入门题目(感受下模板怎么用的) (PS:文中蓝色字体都可以点进去查看百度原文) 附赠数论入门训练专题:点我打开专题(题目顺序基本正常,用以配套数论入门) 一.同余定理 简单粗暴的说就是:若 a-b == m 那么 a%m == b%m 这个模运算性质一眼看出...直接上入门水题: Reduced ID Numbers 附AC代码(这个也没啥模板....知道就好) #inclu

bzoj 2186 [Sdoi2008]沙拉公主的困惑 欧拉函数

bzoj 2186 [Sdoi2008]沙拉公主的困惑 题意: 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量.现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可.R是一个质数. 限制: 数据组数T:1 <= T <= 10000 R <= 1e9+10 1 <= N,M <=10000000