您的位置:首页 > 其它

[模板][数论][gcd+exgcd+sieve+power+euler_phi+euler_table+inv]

2016-11-14 22:14 344 查看
NOIP临近,,写写模板。。。

求逆元:

扩展欧几里得求逆元

适用范围:常数小,适合单个求逆元

限制:gcd(a,n)==1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define FROP "inv"
#define LL long long
using namespace std;
int n=100,mod=1e9+7,inv[105];
void exgcd(int a,int b,int& d,int &x,int &y)
{
if(!b){d=a;x=1;y=0;}
else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
}
int main()
{
freopen(FROP".out","w",stdout);
for(int i = 1; i <= n; i++)
{
int d,x,y;
exgcd(i,mod,d,x,y);//i mod mod 的逆元
inv[i]=(x%mod+mod)%mod;
}
for(int i = 1; i <= n; i++)
printf("%d,",inv[i]);
return 0;
}


费马小定理求逆元

适用范围:若mod是,inv=a^(mod-2)

否则inv=a^(phi(mod)-1),,所有前提条件,a,与mod互素。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define FROP "inv"
#define LL long long
using namespace std;
int n=100,mod=1e9+7,inv[105];
int euler_phi(int n)
{
int ans=n;
int m= sqrt(n+0.5);
for(int i = 2; i <= m; i++)if(n % i==0)
{
ans=ans/i*(i-1);
while(n%i==0)n/=i;
}
if(n>1)ans=ans/n*(n-1);
return ans;
}
int power(int a,int b)
{
if(!b)return 1;
if(b==1)return a;
int p=power(a,b/2);
p=(LL)p*p%mod;
if(b%2)return p*a%mod;
return p;
}
int main()
{
freopen(FROP".out","w",stdout);
int eul=euler_phi(mod);
for(int i= 1; i <= 100; i++)
{
printf("%d,",power(i,eul-1));
}
return 0;
}


线性求逆元

没有限制,,表示爱上线性求逆元了。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define FROP "inv"
#define LL long long
using namespace std;
int n=100,mod=1e9+7,inv[105];
int main()
{
freopen(FROP".out","w",stdout);
inv[1]=1;
for(int i = 2; i <= n; i++)
inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod;
for(int i = 1;i <= n; i++)
printf("%d,",inv[i]);
return 0;
}


gcd模板

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}


筛法求素数

void sieve(int n)
{
int m = sqrt(n+0.5);
for(int i = 2; i <= m; i++)if(!vis[i])
for(int j = i*i; j <= n; j+=i)vis[j]=1;
}
int main()
{
freopen(FROP".in","r",stdin);
freopen(FROP".out","w",stdout);
sieve(100);
for(int i = 1;i <= n; i++)
if(!vis[i])printf("%d,",i);
return 0;
}


单数欧拉函数

int euler_phi(int n)
{
int ans=n;
int m= sqrt(n+0.5);
for(int i = 2; i <= m; i++)if(n % i==0)
{
ans=ans/i*(i-1);
while(n%i==0)n/=i;
}
if(n>1)ans=ans/n*(n-1);
return ans;
}


求1-n的欧拉函数

O(nloglogn)

int phi[100];
void euler_table(int n)
{
for(int i = 2; i <= n; i++)phi[i]=0;
phi[1]=1;
for(int i = 2; i <= n;i++)if(!phi[i])
for(int j= i; j <= n; j+=i)
{
if(!phi[j])phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}


快速幂

int power(int a,int b)
{
if(!b)return 1;
if(b==1)return a;
int p=power(a,b/2);
p=(LL)p*p%mod;
if(b%2)return p*a%mod;
return p;
}


差不多了,还有些以后再说吧。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gcd power phi