数论板子

来源:互联网 发布:iphone 投影到mac 编辑:程序博客网 时间:2024/06/07 08:07
//筛法求MAXN范围以内的素数表,其中需要借用一个bool数组vis  void prime_table()   {      int i,j;      for(i = 2;i <= MAXN;i++)      {          if(!vis[i])          {              prime[++cnt] = i;                //cnt为素数计数器              for(j = i*i;j <= MAXN;j += i)                  vis[j] = true;          }      }  }  
//高效算法同时打出prime表与phi表,比单独用筛法打出phi表与prime表快3倍左右void prime_phi_table(){    int i,j;    phi[1] = 1;    for(i = 2;i <= MAXN;i++)    {        if(!vis[i])        {            prime[++cnt] = i;            phi[i] = i-1;        }        for(j = 1;j <= cnt && i * prime[j] <= MAXN;j++)        {            vis[i * prime[j]] = true;            if(i % prime[j] == 0)            {                phi[i * prime[j]] = phi[i] * prime[j];                break;            }            else phi[i * prime[j]] = phi[i] * (prime[j] - 1);        }    }}
//求n的欧拉函数值  int phi(int n)  {      int t = sqrt(n + 0.5);      int ans = 1;      for(int i = 2;i <= t;i++)      {          if(n % i == 0)          {              ans *= (i-1);              n /= i;              while(n % i == 0)              {                  ans *= i;                  n /= i;              }          }          if(n == 1) break;      }      if(n > 1) ans *= (n-1);      return ans;  }  
//求a与b的最大公约数,其中b > a  int gcd(int a,int b)   {      if(a > b) swap(a,b);      while(a)      {          int t = b % a;          b = a;          a = t;      }      return b;  }  
//扩展欧几里得,ax + by = c,求出x,y的一组整数解,d = gcd(a,b),当 c % d != 0时,无整数解  void exgcd(int a,int b,int &d,int &x,int &y)  {      if(!b) {d = a; x = 1; y = 0;}      else {              exgcd(a%b,a,d,y,x);              y -= x*(a/b);      }  }  
<pre name="code" class="cpp">//在上述不定方程中,若方程为ax + by = gcd(a,b),当求出一组整数解x0,y0后  //关于x,y的通解则有:x = x0 + b/d * k , y = y0 - a/d * t (t为任意整数)  [cpp] view plain copy<pre name="code" class="cpp">//由于模运算的特殊性,在计算(a / b) % m 时,当a、b太大需要事先取模,此时该式不能直接写为:  // ((a % m) / (b % m)) % m  // 而是需要先算出 ax≡1(mod m),此时x为a的逆元。这个式子等价于ax + my = 1(此时gcd(a,b)必须为1,否则无解)  // 此时使用扩展欧几里得即可解决:exgcd(a,m,d,x,y);当m为质数时,x = (a^(m-2)) % m;  //但求出来的x可能为负数,需要写成(x + m) % m  // 最终式子为 (a / b) % m = a * x % m  
//对整数n进行唯一分解,A[cnt].prime为n的第cnt个质因子,A[cnt].num为该质因子的指数  void dissolve(int n)  {      int i;      int t = sqrt(n + 0.5);      for(i = 2;i <= t;i++)      {          if(n % i == 0)          {              cnt++;              A[cnt].prime = i;              while(n % i == 0)              {                  A[cnt].num++;                  n /= i;              }          }          if(n == 1) break;      }      if(n > 1)                     //若n为质数      {          cnt++;          A[cnt].prime = n;          A[cnt].num = 1;      }  }  
//求1~n行的组合数,即杨辉三角表,注意,为了防止数组越界,此时C(0,0)为数组第一行,且第n行代表C(n-1,k)  void Make_up_num_table(int n)  {      C[1][1] = 1;      C[2][1] = 1; C[2][2] = 1;      for(int i = 3;i <= n;i++)          for(j = 1;j <= i;i++)              C[i][j] = C[i-1][j-1] + C[i-1][j];  }  [cpp] view plain copy//求第n行的组合数,和杨辉三角的区别是这个只求一行但是为O(n)的时间复杂度  //注意,这个函数出于求解方便,第n行代表的是C(n,k)且是从0开始存,与上一个函数不同  void Make_up_num(int n)  {      A[0] = 1;      for(int i = 1;i <= n;i++)          A[i] = A[i-1] * (n - i + 1) / i;  }  
原创粉丝点击