zoukankan      html  css  js  c++  java
  • 数论入门基础整理

    *有误欢迎大佬斧正*

    基本定理:

    威尔逊定理:一个数p为素数的充要条件是p|(p-1)!+1

    费马小定理:对于素数p,以及整数a,如有(a,p)=1,则a^(p-1)=1(mod p)

    欧拉定理:对于任意两个互素整数a,m ,a^φ(m) =1 (mod m)φ为欧拉函数,表示小于p且与p互素的数个数

    欧拉函数求解:

     1 int euler(int x)
     2 {
     3     int res = x, n = x;
     4     for (int i = 2; i * i <= n; i++)
     5         if (n % i == 0)
     6         {
     7             res = res / i * (i - 1);
     8             while (n % i == 0)
     9                 n /= i;
    10         }
    11     if (n > 1)
    12         res = res / n * (n - 1);
    13     return res;
    14 }
    求一个欧拉函数值
    1 void getEuler()
    2 {
    3     for (int i = 1; i < maxn; i++)
    4         e[i] = i;
    5     for (int i = 2; i < maxn; i++)
    6         if (e[i] == i)
    7             for (int j = i; j < maxn; j += i)
    8                 e[j] = e[j] / i * (i - 1);
    9 }
    筛法求区间每个数欧拉函数

    扩展欧拉定理:将欧拉定理延申到了 (a,m) !=1 的情况,可用于大指数运算

     <code>

    孙子定理(中国剩余定理):

    对于形如的方程组,m互素

    M=m1*m2..mn, M= M/mi, ti=Mi在模mi意义下的乘法逆元(关于乘法逆元可以参考费马小定理扩展欧几里得算法),解为

    x=a1*t1*M1+a2*t2*M2+...an*tn*Mn+kM,k为整数原方程最小解为x mod M

     1 /*
     2     普通孙子定理/中国剩余定理,求解模数互素的同余方程组
     3     m除数,r余数
     4  */
     5 ll exgcd(ll a, ll b, ll &x, ll &y) //求逆元
     6 {
     7     if (b == 0)
     8     {
     9         x = 1, y = 0;
    10         return a;
    11     }
    12     ll ret = exgcd(b, a % b, y, x);
    13     y -= (a / b) * x;
    14     return ret;
    15 }
    16 
    17 ll crt()
    18 {
    19     ll d, x, y, ret = 0;
    20     ll temp;
    21     ll M = 1;
    22     for (int i = 0; i < n; i++)
    23         M *= m[i]; //m是除数
    24     for (int i = 0; i < n; i++)
    25     {
    26         temp = M / m[i];
    27         d = exgcd(m[i], temp, x, y);       //求temp在模mi意义下的逆元
    28         ret = (ret + y * temp * r[i]) % M; //b是余数
    29     }
    30     return (ret + M) % M;
    31 }
    中国剩余定理

    对于m不互素的情况,需要用扩展欧几里得进行两两合并求解()

     1 /*
     2     扩展中国剩余定理
     3     可求解m不互质的同余方程组
     4     m除数,r余数
     5  */
     6 
     7 ll exgcd(ll a, ll b, ll &x, ll &y)
     8 {
     9     if (b == 0)
    10     {
    11         x = 1, y = 0;
    12         return a;
    13     }
    14     ll ret = exgcd(b, a % b, y, x);
    15     y -= (a / b) * x;
    16     return ret;
    17 }
    18 ll excrt()
    19 {
    20     ll M = m[0], R = r[0], x, y, d;
    21     for (int i = 1; i < n; i++)
    22     {
    23         d = exgcd(M, m[i], x, y);
    24         if ((R - r[i]) % d)
    25             return -1;
    26         x = (R - r[i]) / d * x % m[i];
    27         R -= M * x;
    28         M = M / d * m[i];
    29         R %= M;
    30     }
    31     return (R % M + M) % M;
    32 }
    扩展中国剩余定理

    素数与合数:

    唯一分解定理

    一个自然数x可以唯一分解为x = p1r1p2r2...pnrn  (p为素数,r为正整数)

    x的所有因子个数:(1 + r1) * ( 1 + r)...( 1 + r)

    x的所有因子之和:( 1 + p+ p12 + p13...p1r1)( 1 + p+ p22  +...+p2r2)...( 1 + p+ pn+ ...+ pnrn)

    x的所有因子之和: phi(n)*n/2, (phi为欧拉函数,表示小于n且与n互素的数个数)

    反素数

    定义g(x)为x的因子个数,若对于所有的0 < i< x,都有g(i)<g(x)则称x为反素数

    反素数性质1:一个反素数的素因子必然是从2开始的连续素数

    反素数性质2:若n为反素数,则n= p1r1p2r2...pnrn ,其中r1>=r2>=..rn

    N!的素因子分解:

    即幂可由后边和式计算得到

    1 int f(ll n, ll p)
    2 {
    3     if (n == 0)
    4         return 0;
    5     return f(n / p, p) + n / p;
    6 }
    求n!里因子p的个数
     素数筛

    埃氏筛素数(no code)

     
     1 for (int i = 2; i <= maxn; i++)
     2 {
     3     if (!vis[i])
     4         prime[pcnt++] = i;
     5     for (int j = 0; j < pcnt && i * prime[j] <= maxn; j++)
     6     {
     7         vis[i * prime[j]] = 1;
     8         if (i % prime[j] == 0)
     9             break;
    10     }
    11 }
    欧拉筛素数
     1 /*
     2     区间素数筛,maxn是区间长度,[a,b]
     3  */
     4 const int maxn = 1e5 + 10; //区间最大长度
     5 bool isprime1[maxn], isprime2[maxn];
     6 int solve(ll a, ll b)
     7 {
     8     for (ll i = 0; i * i <= b; i++)
     9         isprime1[i] = 0;
    10     for (ll i = 0; i <= b - a; i++)
    11         isprime2[i] = 1;
    12     for (ll i = 2; i * i <= b; i++)
    13     {
    14         if (!isprime1[i])
    15         {
    16             for (ll j = i + i; j * j <= b; j += i)
    17                 isprime1[j] = 1;
    18             for (ll j = max(2LL, (a + i - 1) / i) * i; j <= b; j += i)
    19                 isprime2[j - a] = 0;
    20         }
    21     }
    22     int sum = 0;
    23     for (int i = 0; i <= b - a; i++)
    24         if (isprime2[i])
    25             sum++;
    26     if (a == 1)
    27         --sum;
    28     return sum;
    29 }
    区间素数筛
    MIller-Robin素数测试法

    费马小定理:对于素数p和任意整数a,若(a,p)=1,有ap-1 ≡ 1 (mod p)。相反的,满足ap-1 ≡ 1 (mod p),p也几乎一定是素数。

    伪素数:如果n是一个正整数,如果存在和n互素的正整数a满足 an-1 ≡ 1(mod n),我们说n是基于a的伪素数。如果一个数是伪素数,那么它几乎肯定是素数。

    Miller-Rabin测试:不断选取不超过n-1的基b(s次),计算是否每次都有bn-1 ≡ 1(mod n),若每次都成立则n是素数,否则为合数。 

     1 ll powerMod(ll a, ll b, ll mod)
     2 {
     3     ll ret = 1LL;
     4     a %= mod;
     5     while (b)
     6     {
     7         if (b & 1LL)
     8             ret = multiMod(ret, a, mod), --b;
     9         b >>= 1LL;
    10         a = multiMod(a, a, mod);
    11     }
    12     return ret;
    13 }
    14 
    15 //Miller-Rabin测试,测试n是否为素数
    16 bool Miller_Rabin(ll n, int repeat)
    17 {
    18     if (2LL == n || 3LL == n)
    19         return true;
    20     if (!(n & 1LL))
    21         return false;
    22 
    23     //将n分解为2^s*d
    24     ll d = n - 1LL;
    25     int s = 0;
    26     while (!(d & 1LL))
    27         ++s, d >>= 1LL;
    28 
    29     srand((unsigned)time(0));
    30     for (int i = 0; i < repeat; ++i)
    31     {                                //重复repeat次
    32         ll a = rand() % (n - 3) + 2; //取一个随机数,[2,n-1)
    33         ll x = powerMod(a, d, n);
    34         ll y = 0LL;
    35         for (int j = 0; j < s; ++j)
    36         {
    37             y = multiMod(x, x, n);
    38             if (1LL == y && 1LL != x && n - 1LL != x)
    39                 return false;
    40             x = y;
    41         }
    42         if (1LL != y)
    43             return false;
    44     }
    45     return true;
    46 }
    Miller-Rabin大素数测试
    Pollard-rho大数分解

    --摘自大佬博客https://blog.csdn.net/Sunshine_cfbsl/article/details/52512706

    对于一个大整数n,我们取任意一个数x使得x是n的质因数的几率很小,但如果取两个数x1以及x2使得它们的差是n的因数的几率就提高了,如果取x1以及x2使得gcd(abs(x1−x2),n)>1的概率就更高了。这就是Pollard-Rho算法的主要思想。

    对于满足gcd(abs(x1−x2),n)>1的x1和x2,gcd(abs(x1−x2),n)就是n的一个因数,只需要判断它是否为素数,若为素数,则是n的质因数,否则递归此过程。

    其中判断素数就使用MillerMiller-RabinRabin算法。

    那么我们怎样不断取得x1x1和x2x2呢?
    x1在区间[1,n]中随机出来,而x2则由x[i]=(x[i-1]*x[i-1]%n+c)%n推算出来,其中c为任意给定值,事实证明,这样就是比较优的。

    <code>

    莫比乌斯反演

    专门开了一篇随笔记录,传送门

    原根

    (埋坑)

    勾股数组

    本源勾股数组

    指勾股数中两两互质的勾股数,其他勾股数均可由其翻倍得出。

    求法

    对于一个大于1的奇数p,由其构成的本源勾股数组为$p,leftlfloorfrac{p^2}{2} ight floor,leftlceilfrac{p^2}{2} ight ceil$

    一般勾股数组的求法,寻找一个奇因子,由奇因子生成本源勾股数组,乘上倍数。特别的,2的幂次需要特判

  • 相关阅读:
    用instr 直接取最右端的点的位置:
    ASP FSO操作文件(复制文件、重命名文件、删除文件、替换字符
    Ubuntu 16.04系统下安装RapidSVN版本控制器及配置diff,editor,merge和exploer工具
    Ubuntu 16.04系统下开机提示“无法应用原保存的显示器配置”
    Ubuntu 16.04系统下出现E: 无法下载 http://ppa.launchpad.net/fcitx-team/nightly/ubuntu/dists/xenial/main/binary-amd64/Packages 404 Not Found
    Ubuntu 16.04系统下软件中心Software闪退解决办法
    UEditor富文本WEB编辑器自定义默认值设置方法
    HTML5 移动页面自适应手机屏幕四类方法
    Ubuntu 16.04系统下apt-get和dpkg区别
    jQuery相同id元素 全部获取问题解决办法
  • 原文地址:https://www.cnblogs.com/mooleetzi/p/11298546.html
Copyright © 2011-2022 走看看