<更新提示>

<第一次更新>


<正文>

简单数论

质因子分解

素性测试

素性测试指的是对一个正整数是否为质数的判定,一般来说,素性测试有两种算法:

\(1.\) 试除法,直接尝试枚举因子,时间复杂度\(O(\sqrt n)\)。

\(2.\) \(Miller-Rabin\)算法,利用费马小定理和二次探测定理对素数进行测试,有小概率误判,时间复杂度\(O(log_2n)\)。

\(Code:\)

inline bool judge(long long x,long long p)
{
if ( x % p == 0 || quickpow( p%x , x-1 , x ) != 1 ) return false;
register long long k = x-1 , val;
while ( ( k & 1 ) == 0 )
{
val = quickpow( p%x , k>>=1 , x );
if ( val != 1 && val != x-1 ) return false;
if ( val == x-1 ) return true;
}
return true;
}
inline bool MillerRabin(long long x)
{
if ( x == 2 ) return true;
if ( x < 2 || ( x & 1 ) == 0 ) return false;
for (int i=0;i<10;i++)
{
if ( x == P[i] ) return true;
if ( !judge( x , P[i] ) ) return false;
}
return true;
}

质因子分解

质因子分解则指的是对一个正整数按照算术基本定理的形式进行分解,也有两种常用算法:

\(1.\) 试除法,直接尝试枚举因子,时间复杂度\(O(\sqrt n)\)。

\(2.\) \(Pollard's\ Rho\)算法,配合\(Miller-Rabin\)算法对整数进行随机化分解,期望时间复杂度\(O(\sqrt [4]{n}log_2n)\)。

\(Code:\)

inline long long Euclid(long long a,long long b) { return b == 0 ? a : Euclid(b,a%b); }
inline long long Random(void) { return ( 0LL + rand() ) << 30 | rand(); }
inline void PollardsRho(long long n)
{
if ( n == 1 ) return;
if ( MillerRabin( n ) ) { ans = max( ans , n ); return; }
long long x = Random() % n , c = Random() % n , y = x;
for (int i=2,k=2;true;i++)
{
register long long val = Euclid( n + y - x , n );
if ( val > 1 && val < n )
return PollardsRho(val) , PollardsRho(n/val);
if ( i == k ) k <<= 1 , y = x;
x = ( quickmul( x , x , n ) + c ) % n;
if ( x == y ) break;
}
return PollardsRho( n );
}

数论算法

欧几里得算法

利用辗转相除法求两个数的最大公约数,时间复杂度\(O(log_2n)\)。

\(Code:\)

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

扩展欧几里得算法

利用欧几里得算法求不定方程的特解,时间复杂度\(O(log_2n)\)。

\(Code:\)

inline int Extended_Euclid(int a,int &x,int b,int &y,int c)
{
if ( b == 0 ) { x = c/a , y = 0; return a; }
else
{
int p = Extended_Euclid(b,x,a%b,y,c);
int x_ = x , y_ = y;
x = y_ , y = x_ - a / b * y_;
return p;
}
}

类欧几里得算法

利用整除拆分技巧计算整除求和式,时间复杂度\(O(log_2n)\)。

\(Code:\)

inline long long f(long long a,long long b,long long c,long long n)
{
if ( a == 0 ) return ( n + 1 ) * ( b / c ) % Mod;
if ( a >= c || b >= c )
return ( f( a%c , b%c , c , n ) + n * ( n + 1 ) % Mod * INV2 % Mod * ( a / c ) % Mod + ( n + 1 ) * ( b / c ) % Mod ) % Mod;
long long val = ( a * n + b ) / c;
return ( ( n * val % Mod - f( c , c - b - 1 , a , val-1 ) ) % Mod + Mod ) % Mod;
}

中国剩余定理

利用公式计算线性同余方程组的特解,要求模数互质,时间复杂度\(O(nlog_2n)\)。

\(Code:\)

inline void CRT(void)
{
m_ = 1;
for (int i=1;i<=n;i++)
m_ *= m[i];
for (int i=1;i<=n;i++)
M[i] = m_ / m[i];
for (int i=1;i<=n;i++)
{
long long y;
Exeuclid(M[i],t[i],m[i],y,1);
ans += a[i]%m_ * M[i]%m_ * t[i]%m_;
ans %= m_;
}
}

拓展中国剩余定理

利用扩展欧几里得算法每次求一个同余方程的解,然后依次合并,从而求得线性同余方程组的解,不要求模数互质,时间复杂度\(O(nlog_2n)\)。

\(Code:\)

inline long long ExCRT(void)
{
long long m_ = m[1] , x = r[1];
for (int i=2;i<=n;i++)
{
long long x_,y_;
if ( ( r[i] - x ) % Euclid( m_ , m[i] ) ) return -1;
long long p = Exeuclid( m_ , x_ , m[i] , y_ , r[i] - x );
long long Mod = m[i] / p;
//要对当前的解先取模,防止爆longlong
x_ = ( x_ % Mod + Mod ) % Mod;
x += x_ * m_;
m_ = m_ * m[i] / p;
x = ( x + m_ ) % m_;
}
return x;
}

BSGS算法

利用分块思想求解离散对数问题的解,要求模数与底数互质,时间复杂度\(O(\sqrt n)\)。

\(Code:\)

inline long long Baby_Step_Giant_Step(long long a,long long b,long long p)
{
map < long long , long long > hash; hash.clear();
long long t = (long long)sqrt(p) + 1 , mul = 1;
b %= p;
for (int j=0;j<t;j++)
{
hash[ mul * b % p ] = j;
mul = mul * a % p;
}
if ( a % p == 0 ) return b == 0 ? 1 : -1;
a = 1;
for (int i=0;i<=t;i++)
{
long long j = ( hash.find(a) != hash.end() ? hash[a] : -1 );
if ( j >= 0 && i * t - j >= 0 ) return i * t - j;
a = a * mul % p;
}
return -1;
}

ExBSGS算法

利用同余性质缩小模数规模,直至模数与底数互质,使用\(BSGS\)算法求解离散对数,时间复杂度\(O(\sqrt n)\)。

\(Code:\)

inline long long ExBSGS(long long a,long long b,long long p)
{
if ( b == 1 ) return 0;
long long cnt = 0 , d , k = 1;
while ( ( d = Euclid(a,p) ) ^ 1 )
{
if ( b % d ) return -1;
b /= d , p /= d , ++cnt;
k = k * ( a / d ) % p;
if ( k == b ) return cnt;
}
unordered_map < long long , long long > Hash; Hash.clear();
long long t = (long long)sqrt(p) + 1 , mul = 1;
for (int j=0;j<t;j++)
{
Hash[ mul * b % p ] = j;
mul = mul * a % p;
}
for (int i=0;i<=t;i++)
{
long long j = ( Hash.find(k) != Hash.end() ? Hash[k] : -1 );
if ( j >= 0 && i * t - j + cnt >= 0 ) return i * t - j + cnt;
k = k * mul % p;
}
return -1;
}

原根

分解模数可以判定原根的存在性,同时可以根据欧拉定理求解原根。

\(Code:\)

pending further supplement

二次剩余

如果存在原根,则可以利用\(BSGS\)算法计算二次剩余,时间复杂度\(O(\sqrt n)\)。

\(Code:\)

pending further supplement

\(Tonelli–Shanks\)算法可以在\(O(log^2n)\)的时间内计算二次剩余。

\(Code:\)

pending further supplement

\(Cipolla\)算法可以在\(O(log_2n)\)的时间内计算二次剩余。

\(Code:\)

pending further supplement

数论函数

定义和概念

数论函数:定义域为正整数集,陪域为复数域的函数。

积性函数:对于任意\(a,b\in N^+,gcd(a,b)=1\),有\(f(ab)=f(a)f(b)\)的数论函数\(f\)被称为积性函数。

完全积性函数:对于任意\(a,b\in N^+\),有\(f(ab)=f(a)f(b)\)的数论函数\(f\)被称为完全积性函数。

积性函数的性质

\(1.\) 设\(n=\prod p_i^{a_i}\),则有\(f(n)=\prod f(p_i^{a_i})\)。

\(2.\) 若数论函数\(f,g\)均为积性函数,则\(f*g,f/g\)也均为积性函数。

狄利克雷卷积

对于数论函数\(f,g\),我们定义\(f\)和\(g\)的\(dirichlet\)卷积为:

\[(f\times g)(n)=\sum_{d|n}f(d)g(\frac{n}{d})
\]

狄利克雷卷积的性质

\(1.\) 交换律:\(f\times g=g\times f\)。

\(2.\) 结合律:\((f\times g)\times h=f\times (g\times h)\)。

\(3.\) 分配律:\(f\times (g+h)=f\times g+ f\times h\)。

\(4.\) 单位元:\(f\times \epsilon=f\)。

\(5.\) 积性性:若函数\(f,g\)是积性函数,则\(f\times g\)也是积性函数。

莫比乌斯反演

莫比乌斯定理:若\(g=f\times I\),则\(f=g\times \mu\)。

证明:

\[g=I\times f\\ \mu\times g =\mu \times I \times f\\\mu \times g=\epsilon \times f=f
\]

底和顶

\(1.\) \(x\geq n⇔\lfloor x\rfloor\geq n\)。

\(2.\) \(x> n⇔\lceil x\rceil> n\)。

\(3.\) \(x\leq n⇔\lceil x\rceil\leq n\)。

\(4.\) \(x< n⇔\lfloor x\rfloor< n\)。

\(5.\) 对于\(i\in[1,n]\),\(\lfloor \frac{n}{i} \rfloor,\lceil \frac{n}{i} \rceil\)都只有\(O(\sqrt n)\)种不同的取值。

杜教筛

对于计算数论函数\(f\)的前缀和,如果我们能够找到合适的函数\(g\),并能快速计算函数\(g\)和函数\(f\times g\)的前缀和,那么我们就可以快速计算函数\(f\)的前缀和。

公式:

\[\sum_{i=1}^nf(i)=\sum_{i=1}^n(f\times g)(i)-\sum_{i=2}^ng(i)\sum_{j=1}^{\lfloor \frac{n}{i} \rfloor}f(j)
\]

另一种形式,设\(S(n)=\sum_{i=1}^nf(i)\),那么有:

\[S(n)=\sum_{i=1}^n(f\times g)(i)-\sum_{i=2}^ng(i)S \left (\lfloor \frac{n}{i} \rfloor \right )
\]

可以用整除分块和记忆化搜索来计算,当我们线性筛预处理前\(n^{\frac{2}{3}}\)个前缀和时,杜教筛的时间复杂度为\(O(n^{\frac{2}{3}})\)。

\(Code:\)

inline pll BishopSieve(int n)
{
if ( n <= m ) return make_pair( phi[n] , mu[n] );
if ( sum.count( n ) ) return sum[n];
long long res1 = 1LL * n * ( n + 1 ) / 2 , res2 = 1;
for (int l=2,r;l<=n;l=r+1)
{
r = n/l ? min( n/(n/l) , n ) : n;
pll val = BishopSieve( n/l );
res1 -= 1LL * ( r - l + 1 ) * val.first;
res2 -= 1LL * ( r - l + 1 ) * val.second;
}
return sum[n] = make_pair( res1 , res2 );
// 求欧拉函数和莫比乌斯函数的前缀和
}

总结

感觉其实数论算法还有不少没有学,并且最大的问题就是做的题不够多,很多经典的套路还不够熟练,尤其是数论函数这一块。再就是代码不够熟练,还需要多刷题。


<后记>

『正睿OI 2019SC Day7』的更多相关文章

  1. 『正睿OI 2019SC Day8-Day17』

    于是就迎来\(10\)天的自闭考试了,每天写点小总结吧. Day8 第一天就很自闭啊,考题分别是数学题+建模题+图论. 前两道题都没有什么算法,但是难度还是有的,于是就做不太出来,特别是第一题.第二题 ...

  2. 『正睿OI 2019SC Day5』

    网络流 网络流的定义 一个流网络\(G=(V,E)\)为一张满足以下条件的有向图: 每一条边有一个非负容量,即对于任意\(E\)中的\((u,v)\) , 有\(c(u,v)\geq0\). 如果\( ...

  3. 『正睿OI 2019SC Day4』

    总结 今天是一场欢乐的\(ACM\)比赛,于是我队得到了全场倒数的好排名. 好吧,其实还是怪自己不能怪队友啦.对于\(ACM\),可能最主要的还是经验不足,导致比赛的时候有点紧张.虽然队友为了磕一道题 ...

  4. 『正睿OI 2019SC Day1』

    概率与期望 总结 老师上午几乎是在讲数学课,没有讲什么和\(OI\)有关的题目,所以我就做了一点笔记. 到了下午,老师讲完了有关知识点和经典模型,就开始讲例题了.前两道例题是以前就做过的,所以没有什么 ...

  5. 『正睿OI 2019SC Day6』

    动态规划 \(dp\)早就已经是经常用到的算法了,于是老师上课主要都在讲题.今天讲的主要是三类\(dp\):树形\(dp\),计数\(dp\),\(dp\)套\(dp\).其中计数\(dp\)是我很不 ...

  6. 『正睿OI 2019SC Day3』

    容斥原理 容斥原理指的是一种排重,补漏的计算思想,形式化的来说,我们有如下公式: \[\left | \bigcup_{i=1}^nS_i \right |=\sum_{i}|S_i|-\sum_{i ...

  7. 『正睿OI 2019SC Day2』

    分治 普通分治 普通分治是指针对序列或平面问题的分治算法. 思想 普通分治的思想是指将一个序列问题或平面问题通过某种划分方式划分为若干个子问题,直到子问题规模足够小,可以直接回答,再通过合并得到原问题 ...

  8. 10.23 正睿停课训练 Day7

    目录 2018.10.23 正睿停课训练 Day7 A 矩形(组合) B 翻转(思路) C 求和(思路 三元环计数) 考试代码 B1 B2 C 2018.10.23 正睿停课训练 Day7 期望得分: ...

  9. 正睿OI DAY3 杂题选讲

    正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...

随机推荐

  1. disable_function绕过--利用LD_PRELOAD

    0x00 前言 有时候直接执行命令的函数被ban了,那么有几种思路可以bypass 1.使用php本身自带的能够调用外部程序的函数 2.使用第三方插件入(如imagick) 但是这两种无非就是利用ph ...

  2. current transaction is aborted, commands ignored until end of transaction block

    current transaction is aborted, commands ignored until end of transaction block Error updating datab ...

  3. youtube-dll工具使用,很好用!!

    最近喜欢上youtube-dll这个插件,下载东西真的很好用,墙裂推荐,github地址如下 https://github.com/ytdl-org/youtube-dl 安装 1.Linux 1.1 ...

  4. elastalert基本配置说明

    elastalert 配置语法: 简单rule规则: es_host,es_port:查询elasticsearch集群 name: 规则的唯一名称.如果相同,则elastalert不会启动. typ ...

  5. python字典中显示中文

    #coding=utf-8import jsondict={'title':"这是中文"}print json.dumps(dict,ensure_ascii=False,enco ...

  6. springboot 整合 freemarker

    springboot 整合 freemarker 依赖 <parent> <groupId>org.springframework.boot</groupId> & ...

  7. Windows WoW64浅析

    WOW64(Windows-On-Windows 64bit)是X64 Windows操作系统的一个子系统,为32位应用程序提供运行环境.类似的还有WOW32子系统,负责在32位Windows系统上运 ...

  8. 网络协议 19 - RPC协议综述

    这几年微服务很火,想必各位博友或多或少的都接触过.微服务概念中, 各服务间的相互调用是不可或缺的一环.你知道微服务之间是通过什么方式相互调用的吗?     你可能说,这还不简单,用 socket 呗. ...

  9. P1553 数字反转(升级版)

    Emma,关于这道题,我..不想说啥子,也就做了它一个下午左右吧(原由:本人太菜) 补充一个知识点goto语句: 这个东西特别的好用,可以直接无条件调到冒号后面的语句,进行操作. 举个例子: #inc ...

  10. 数据分析,R语言

    数据结构 创建向量和矩阵 1 函数c(), length(), mode(), rbind(), cbind() 求平均值,和,连乘,最值,方差,标准差 1 函数mean(), sum(), min( ...