欧拉定理,欧拉函数

来源:互联网 发布:双十一淘宝客服催单 编辑:程序博客网 时间:2024/04/28 08:14

欧拉函数:ϕ (n) = 1...n中与n互质的数的个数;其中,令n = a1^x1 * a2^x2* .....*ak^xk

ϕ (n) = n*(1-1/a1)*(1-1/a2)*.....*(1-1/ak);


欧拉定理:若a和n互质,则a^ϕ(n)≡1(mod n);若n为质数,则有a^(n-1)≡1(mod n);


求欧拉函数的值

ll oula(ll n)         {      ll i,res=1;      for(i=2;i*i<=n;i++)      {          if(n%i==0)          {              n=n/i;              res=res*(i-1);              while(n%i==0)              {                  n=n/i;                  res=res*i;              }          }          if(n==1)              break;      }      if(n>1)          res=res*(n-1);      return res;  }  


质因数分解求欧拉函数值,降低时间复杂度;

int prime[MAX],mark[MAX],cnt;  void Prime(){    memset(mark,0,sizeof(mark));      cnt = 0;      for (int i=2; i< MAX; i++){          if (!mark[i]) prime[cnt++] = i;          for (int j=0; j<cnt && prime[j]*i <= MAX; j++){              mark[i*prime[j]] = 1;              if (i % prime[j] == 0) break;          }      } }int oula(int x)  {      int res=x;      for(int i=0; i<cnt&&prime[i]*prime[i]<=x; i++)      {          if(x%prime[i]==0)          {              res=res/prime[i]*(prime[i]-1);              while(x%prime[i]==0)              {                  x/=prime[i];              }          }      }      if(x>1) res=res/x*(x-1);      return res;                   }


筛选法求前n个数的欧拉函数值,打表法


int a[MAX];void oula(int n){memset(a,0,sizeof(a));a[1] = 1;for (int i=2; i<=n; i++){if (!a[i]){for (int j = i; j<=n; j += i){if (!a[j]) a[j] = j;a[j] = a[j] / i * (i-1);}}}}


欧拉函数,打表法模板题 poj2478


#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<climits>#include<cctype>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<map>#include<set>#include<string>#include<stack>#define ll long long#define MAX 1000010#define eps 1e-8#define INF INT_MAXusing namespace std;int a[MAX+10];void oula(int n){memset(a,0,sizeof(a));a[1] = 1;for (int i=2; i<=n; i++){if (!a[i]){for (int j = i; j<=n; j += i){if (!a[j]) a[j] = j;a[j] = a[j] / i * (i-1);}}}}int main(){int n;oula(MAX);while (scanf("%d",&n) && n != 0){ll ans = 0;for (int i=2; i<=n; i++) ans += a[i];printf("%lld\n",ans);}return 0;}



利用欧拉定理求高阶幂(a^b^c^d^.....mod P)的模;

由欧拉定理的a^φ(n) = 1(mod n),所以a^b^c^d... mod( P) =  a^(b^c^d.....mod(φ(P))) mod (P) =  a^(b^(c^d....mod(φ(φ(P))))mod(φ(n)))mod (P)

ll mod_mul(ll a, ll b, ll N)  {      ll ret = 0;      while (b)      {          if (b & 1)              ret = (ret + a) % N;          a = 2 * a % N;          b >>= 1;      }      return ret;  }    ll mod_pow(ll x, ll n, ll N)                 {      ll ret = 1;      x %= N;      while (n)      {          if (n & 1)              ret = mod_mul(ret, x, N);          x = mod_mul(x, x, N);          n >>= 1;      }      return ret;  }  ll oula(ll n)         {      ll i,res=1;      for(i=2;i*i<=n;i++)      {          if(n%i==0)          {              n=n/i;              res=res*(i-1);              while(n%i==0)              {                  n=n/i;                  res=res*i;              }          }          if(n==1)              break;      }      if(n>1)          res=res*(n-1);      return res;  }  ll x[MAX];stack<ll>S;ll High_pow(ll p, ll n){for (ll i = 1; i<n; i++){S.push(p);p = oula(p);}for (ll i = n-2; i>=0; i--){p = S.top();S.pop();x[i] = mod_pow(x[i],x[i+1],p);}return x[0];}


纯粹的欧拉公式题目 poj2407

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<climits>#include<cctype>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<map>#include<set>#include<string>#include<set>#define ll long long#define MAX 1000010#define eps 1e-6#define INF INT_MAXusing namespace std;int prime[MAX],vis[MAX],a[MAX];int main(){memset(vis,0,sizeof(vis));int cnt = 0;for (int i=2; i<MAX; i++){if (!vis[i]){prime[cnt++] = i;} for (int j=0; j<cnt && prime[j]*i < MAX; j++){vis[prime[j]*i] = 1;if (i % prime[j] == 0) break;}}int n,c;while (scanf("%d",&n) && n != 0){c = 0;double ans = n;for (int i=0; prime[i] <= n; i++){if (n % prime[i] == 0){a[c++] = prime[i];while (n % prime[i] == 0) n /= prime[i];}}//for (int i=0; i<c; i++) printf("%d ",a[i]); printf("\n"); for (int i=0; i<c; i++)ans = ans*(1.0 - 1.0 / a[i]);printf("%d\n",(int)(ans+eps));}return 0;}

poj3696欧拉定理的应用,以及熟悉模算术运算;

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<climits>#include<cctype>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<map>#include<set>#include<stack>#include<string>#define ll long long#define MAX 1000000#define INF INT_MAX#define eps 1e-8using namespace std;ll N;ll gcd(ll a, ll b){    if (b == 0) return a;    return gcd(b, a%b);}ll mod_mul(ll a, ll b)     //模N下的乘法运算 {    long long ret = 0;    while (b)    {        if (b & 1)            ret = (ret + a) % N;        a = 2 * a % N;        b >>= 1;    }    return ret;}ll mod_pow(ll x, ll n)       //模N下的幂运算 {    long long ret = 1;    x %= N;    while (n)    {        if (n & 1)            ret = mod_mul(ret, x);        x = mod_mul(x, x);        n >>= 1;    }    return ret;}ll oula(ll n)          //求n的欧拉函数值 {      ll i,res=1;      for(i=2;i*i<=n;i++)      {          if(n%i==0)          {              n=n/i;              res=res*(i-1);              while(n%i==0)              {                  n=n/i;                  res=res*i;              }          }          if(n==1)              break;      }      if(n>1)          res=res*(n-1);      return res;  }  ll a[MAX],cnt;void split(ll n){                  //n因式分解     ll m = (ll)sqrt(n+0.5);    cnt = 0;    for (ll i=1; i<=m; i++){        if (n % i == 0){            a[cnt++] = i;            a[cnt++] = n / i;        }    }}int main(){    ll L,cas = 0;    while (scanf("%lld",&L) && L > 0){        cas++;        N = 9*L / gcd(9*L,8);        if (gcd(10,N) > 1){            printf("Case %lld: %lld\n",cas,0LL);            continue;        }        ll n = oula(N);        split(n);        sort(a,a+cnt);        for (int i=0; i<cnt; i++){            if ( mod_pow(10,a[i])  == 1){                printf("Case %lld: %lld\n",cas,a[i]);                break;            }        }    }    return 0;}

大致解题思路:

最终答案为x个8,则可以表示为(10^x-1)*(8/9),则有(10^x-1)*(8/9) = 0(mod L),化简得到10^x = 1(mod(9*L/gcd(9*L,8));

则题目变成一个离散对数问题:

若gcd(10,n) != 1 则无解,否则有欧拉定理的10^ϕ (n) = 1mod(n),即至少会存在一个解

又因为10^x = 1(mod n)成立的最小x是ϕ (n)的约数,所以从小到大枚举约数求解。










0 0