数论基础部分
改名!感觉还是把数学都写到这里吧。
数学菜批是这样的。
数论分块
算是前置芝士了,很多莫反题都要用这玩意。
假如现在我们有 $\left \lfloor \frac{n}{i} \right \rfloor $ 这样的式子,能够发现,其实他会有一大段值的取值是一样的,比如令 \(n = 30\),那么从 \(8\)~\(10\) 的取值都是相同的,当 \(n\) 很大的时候,这个块的长度也会很大,某些题中,我们只需要用到他的取值,那么我们遍利所有的 \(i\) 显然是冗余的,只要找到每一个块的右端点挨个看就好了,现在考虑如何找这个右端点。
甩个结论 $\left \lfloor \frac{n}{\left \lfloor \frac{n}{i} \right \rfloor } \right \rfloor $ 就是右端点,考虑证明。
首先令 $k = \left \lfloor \frac{n}{i} \right \rfloor $,那么显然 \(k \leq \frac{n}{i}\),那么就会有 $\left \lfloor \frac{n}{k} \right \rfloor \ge \left \lfloor \frac{n}{\frac{n}{i}} \right \rfloor = \left \lfloor i \right \rfloor = i $,感性理解,当 \(i\) 取到最靠右的值的时候,就是 $\left \lfloor \frac{n}{k} \right \rfloor $,也就证明了上面的结论,所以数论分块的代码写出来也是非常简洁的。
例题 P3579 [POI2014] PAN-Solar Panels
好像是因为这个题才来写的这个笔记
不是很板,带一点思考量,我们首先能够发现,假如有一个 \(gcd\) 能满足答案,感性来看就是他一定会被同时包含在 \([a,b]\) 和 \([c,d]\) 中间,那么如果要判断这个答案,就是令 $\left \lfloor \frac{a}{i} \right \rfloor < \left \lfloor \frac{b}{i} \right \rfloor $ 时才能满足条件,\([c,d]\) 同理。那么现在就是要考虑怎么判断令 \(i\) 同时满足两个不等式了,这就可以考虑上面的整除分块了,我们只需要枚举商,判断是否被区间包含即可,复杂度 \(O(n \sqrt V)\)。
莫比乌斯反演
我总算是懂了,现在给一个莫比乌斯函数。
基于没有平方因子的性质,我们可以用欧拉筛求这东西,具体就是:
inline void GP(ll n){
	vis[1]=1;mu[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]) prime[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0) break;
			mu[i*prime[j]]=-mu[i]; 
		}
	}
	fo(2,i,n) mu[i]+=mu[i-1];
}
莫比乌斯函数还有个性质:
也就是他等价于 \(\zeta (n)\),\(\mu * 1 = \zeta\),其中 \(\zeta\) 是黎曼函数,\(*\) 是狄利克雷卷积,所以在狄利克雷生成函数里面,莫比乌斯函数等价于常值函数 \(1\) 的逆元。
啊啊啊,好多笔误。
考虑证明:
设 \(n = \prod_{i=1}^{k} p_i^{c_i}\),\({n}'=\prod_{i=1}^{k} p_i\)。
显然,由二项式定理:
所以当且仅当 \(k=0\) 时原式值为 \(1\),也就是仅当 \(n=1\) 时成立。
有个小结论,这个还是很好理解的,\([\gcd(i,j)=1] = \sum_{d|\gcd(i,j)} \mu(d)\)
现在有了上面的结论,我们开始莫反的推导,假设现在有两个在非负数域上定义的函数 \(f(i)\) 和 \(F(i)\),并且有 \(F(n) = \sum_{d|n} f(d)\),那么我们存在反演结论 \(f(n) = \sum_{d|n} \mu(d)F(\left \lfloor \frac{n}{d} \right \rfloor)\)。
考虑证明,首先有:
这一步只是将式子变了一下,然后我们更换顺序:
然后由莫比乌斯函数的性质可以得知,当且仅当 \(\left \lfloor \frac{n}{i} \right \rfloor = 1\) 的时候,后半部分的式子才不为 \(0\),此时才代回前面式子,可以得到:
得证。
其实莫反还有一种形式结论 \(f(n) = \sum_{d|n} \mu(\frac{n}{d})F(d)\),这种也是好证明的。
到这里就差不多了,还有一些例题,之后会慢慢补上的。
P3455 [POI2007] ZAP-Queries
写出原答案式子:
把 \(k\) 提出来扔到前面去:
直接莫反:
再改一下枚举顺序:
发现 \(\mu(d)\) 可以扔到前面去,那后面一坨就没什么意义了:
筛一下 \(\mu(d)\) 这样我们就有了 \(O(n)\) 的解决办法,可是是多组,这样显然过不去。
进一步考虑数论分块,现将 \(n\) 和 \(m\) 除以 \(k\) 之后就是数论分块的一般形式了,直接套板子求个和就好了,复杂度 \(O(n\sqrt n)\)。
P2398 GCD SUM
双倍经验,还是上面那个式子,枚举一下 \(\gcd(i,j)\) 的值就好了。
P1829 [国家集训队] Crash的数字表格 / JZPTAB
晚自习 40min 搞出来了,但是式子长的要死。
写出原式子 \(\sum_{i=1}^{n} \sum_{j=1}^{m} \operatorname{lcm} (i,j)\),把 lcm 拆开,写成 \(\sum_{i=1}^{n} \sum_{j=1}^{m} \frac{ij}{\gcd(i,j)}\)。
感觉这个分数形式很难搞,我们仍然采用枚举 gcd 的想法搞,这里跳了一步,直接把 \([\gcd(i,j) = k]\) 弄到外面去,然后会留下 \(k^2\) 的常数:
把 \(k^2\) 放到外面,然后常规莫反套路,改一下 gcd 式子再莫反:
之后把无关的 \(d^2\mu(d)\) 扔出去,发现 \(i\) 与后面的一个求和无关,放到前面:
这样的话,我们可以处理 \(A_i = \sum_{j=1}^{i} j\) 就可以把式子表示成:
把后面记作 \(f(n) = \sum_{d=1}^{n} d^2\mu(d) A_{\left \lfloor \frac{n}{d} \right \rfloor} A_{\left \lfloor \frac{m}{d} \right \rfloor}\),这东西只要预处理 \(\sum \mu(d) d^2\) 就可以数论分块了,复杂度 \(O(\sqrt n)\)。
可是还有前面枚举 \(k\) 的 \(O(n)\),这样总的是 \(O(n\sqrt n)\),无法通过。
写出式子 \(\sum_{k=1}^{n} k~f(\left \lfloor \frac{n}{k} \right \rfloor)\),发现这东西可以再套一个数论分块,这样总的复杂度就是 \(O(n)\) 了,可以通过。
P2257 YY的GCD
滚回来更新了,这题好像四个月前就在做题计划里了,一直没补(
好像有一个单测的简化版,简单写一下式子吧,我们默认令 \(n < m\):
然后莫反:
把 \(\mu(d)\) 提到前面去,自然变成:
这样单次时间复杂度就是 \(O(V\sqrt n)\) 了,其中 \(V\) 表示 \(prime\) 的大小,可是这题多测,\(O(TV\sqrt n)\) 跑不过去,考虑再优化:
令 \(T=dk\),我们改为优先枚举 \(T\),则式子变成:
这时候我们就发现后面的东西可以预处理了,在欧拉筛之后枚举一下倍数是 \(O(n\log n)\) 的。
P3704 [SDOI2017] 数字表格
大力膜拜 lhc!!!
写出式子,默认 \(n < m\),\(f(i)\) 表示 fib 序列:
枚举 \(\gcd\),得到:
发现 \(f(d)\) 进行乘法的次数就是 \(\sum_{i=1}^n \sum_{j=1}^m [gcd(i,j)=1]\):
之后正常莫反套路:
然后我们里面的 \(\sum\) 拿出来,对里面分成两部分:
模仿上一题的优化套路,我们先令 \(T=kd\),然后枚举 \(T\),改一下式子:
我们设 \(F(n) = \prod_{d|n} f(d)^{\mu(\frac{n}{d})}\),原式变成:
因为 \(n\leq 10^6\),所以 \(F(T)\) 是可以枚举因数做到预处理 \(O(n\log n)\) 的,再做一遍数论分块就好了,复杂度大概是 \(O(T\sqrt n \log n)\)。
扩展欧几里得算法
求解不定方程,形似 \(ax + by = \gcd(a,b)\) 的解。
洛谷的模板题是求 \(ax+by =c\),因为显然有 \(\gcd(a,b) | (ax+by)\),然后就要保证 \(\gcd(a,b) | c\),把通解形式改写一下就好了。
感觉 oi-wiki 的证法比较好理解,写一下:
我们设:
存在 \(ax_0 + by_0 = \gcd(a,b)\) 和 \(bx_1 + (a \mod b)y_1 = \gcd(b,a \mod b)\)。
要证明这俩方程是等价的,首先有 \(\gcd(a,b) = \gcd(b,a\mod b)\),然后写成 \(ax_0 + by_0 = bx_1 + (a\mod b)y_1\)。
对于 \(a\mod b\),等价于 \(a = a - \left \lfloor \frac{a}{b}\right \rfloor \times b\)。
推一下式子,有 \(ax_0 + by_0 = ay_1 + b(x_1 - \left \lfloor \frac{a}{b}\right \rfloor y_1 )\)。
那么就有 \(x_0 = y1\),\(y_0 = x_1 - \left \lfloor \frac{a}{b}\right \rfloor y_1\),递归求解即可。
inline ll Exgcd(ll a,ll b,ll &x,ll &y)
{
	if(!b) return x=1,y=0,a;
	ll d=Exgcd(b,a%b,x,y);
	ll t=x;x=y,y=t-(a/b)*y;return d;
}
卢卡斯定理
对于一个质数 \(p\),我们可以用卢卡斯定理求 \(\binom{n}{m}\mod p\)。
有结论是 $Lucas(n,m)=Lucas(n/p,m/p) \times \binom{n \mod p}{m \mod p} $,这个是直接递归下去求就好了,复杂度大概是 \(O(\log n)\)?
等我尽量补一下证明。
inline ll qpow(ll a,ll b){return (!b?1ll:qpow(a*a%p,b>>1)*((b&1ll)?a:1ll))%p;}
inline ll C(ll n,ll m){if(m>n) return 0;return pre[n]*qpow(pre[m],p-2)%p*qpow(pre[n-m],p-2)%p;}
inline ll Lucas(ll n,ll m){return (!m?1ll:C(n%p,m%p)*Lucas(n/p,m/p)%p);}
signed main(){
	ll t;read(t);
	while(t--)
	{
		read(n),read(m),read(p);
		pre[0]=1;fo(1,i,max(n+m,p)) pre[i]=pre[i-1]*i%p;
		wr(Lucas(n+m,n)),pr; 
	}
}
扩展欧拉定理
哦这个好久之前就写过博客了,写的好丑啊我靠。
欧拉函数
这里给出定义 :
我们记 \(\varphi(n)\) 为小于等于\(n\)与\(n\)互质的数的个数。
展开是这样的:
\(\varphi(x) = \sum_{i=1}^{x} [~\gcd~(i,n)=1]\)
欧拉筛显然可以把它筛出来:
inline void check_mul(ll n){
	vis[1]=1,mul[1]=1;
	fo(2,i,n)
	{
		if(!vis[i]) prime[++cnt]=i,f[i]=i,mul[i]=-1;
		for(ll j=0;j<cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]] = 1;
			f[i*prime[j]] = f[i] + 1;
			if(i%prime[j]==0){
				mul[i*prime[j]]=0;
				break;
			}
			mul[i*prime[j]]=-mul[i];
		}
	}
}
对于单个欧拉函数的求法:
欧拉函数是特殊的积性函数,有性质 \(\varphi(ab) = \varphi(a) \varphi(b)\),对于任意一个正整数 \(a\),有 \(a = \prod_{i=1}^n p_i^{k_{i}}\)。
进一步,我们可以发现对于任意一个质数 \(p\),有 \(\varphi(p^k) = p^{k-1} (p-1)\)。
因此,有 \(\varphi(a) = \prod_{i=1}^n \varphi(p_i^{k_i}) = \prod_{i=1}^n p_i^{k_i-1}(p_i-1) = \prod_{i=1}^n p_i^{k_i} \prod_{i=1}^n (1-\frac{1}{p_i}) = a \prod_{i=1}^{n} (1-\frac{1}{p_i})\)
这样我们就可以在 \(O(\sqrt a)\) 的复杂度内处理出 \(\varphi(a)\)。
欧拉定理
直接给出结论:
若 \(gcd(a,m)=1\) , 则有 \(a^{\varphi(m)}\equiv 1\) \((mod\) \(m)\)。
证明比较简单:
我们假定 \(r_1,r_2,r_3...r_{\varphi(m)}\) 为模 \(m\) 下的一个剩余系,则 \(ar_1,ar_2...ar_{\varphi(m)}\) 也为模 \(m\) 下的一个剩余系,所以有 \(r_1\cdot r_2 \cdot r_3 \cdot ... \cdot r_{\varphi(m)}\equiv ar_1 \cdot ar_2 \cdot ar_3 \cdot ... \cdot ar_{\varphi(m)}\) 同时约去剩余系 , 即可得到上述公式 \(a^{\varphi(m)}\equiv 1\) \((mod\) \(m)\)。
具体证明可以参考 oiwiki。
拓展欧拉定理
对于欧拉定理,只有在 \(gcd(a,m)=1\) 时才能使用,那么我们推广一下便可得到:
证明过程类似跳循环节,此处不再写。
那么,我们只需要预处理出 \(\varphi(m)\) 就可以按照拓展欧拉定理进行降幂了。
inline bool read(ll &opp,ll mod){ll x=0,t=1;char ch;ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-'){t=-1;}ch=getchar();}ll flag=0;while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);if(x>=mod) flag=1,x%=mod;ch=getchar();}opp=x*t;return flag;}
inline void wr(ll x){if(x<0){putchar('-');x=-x;}if(x>9){wr(x/10);}putchar(x%10+'0');}
inline ll qpow(ll a,ll b,ll mod){return (!b?1ll:qpow(a*a%mod,b>>1,mod)*((b&1)?a:1ll))%mod;}
ll a,m,b;
signed main(){
	read(a),read(m);
	ll k=m,phi=m;
	fo(2,i,sqrt(m))
	  if(k%i==0)
	  {
		phi=phi/i*(i-1);
		while(k%i==0) k/=i;
	  }
	if(k>1) phi=phi/k*(k-1);
	ll op=read(b,phi);if(op) b+=phi;
	wr(qpow(a,b,m)),pr;
}
中国剩余定理(CRT)
考虑我们现在有同余方程组:
对于这个方程组的求解,我们有结论:
令 \(n = \prod b_i\),\(m_i = \frac{n}{b_i}\),\(c_i = m_i (m_i^{-1} \mod b_i)\)。
则有 \(ans = \sum a_i c_i\)。
考虑证明,我们要证明 \(ans \equiv a_i \pmod{b_i}\)。
对于任意 \(i\neq j\),显然有 \(m_j \equiv c_j \equiv 0 \pmod{b_i}\),而又有 \(c_i \equiv m_i (m_i^{-1} \mod b_i) \equiv 1 \pmod{b_i}\)。
于是就可以推到出,对于每一个 \(i\),有:
得证,CRT 的正确性就是需要 \(b_i\) 互质,不互质的话就需要 exCRT 了,求 \(m^{-1}\) 时需要用到 exgcd。
inline ll Exgcd(ll a,ll b,ll &x,ll &y)
{
	if(!b) return x=1,y=0,a;
	ll d=Exgcd(b,a%b,x,y);
	ll t=x;x=y,y=t-(a/b)*y;return d;
}
signed main(){
	read(n);fo(1,i,n) read(a[i]),read(b[i]),sum*=a[i];
	fo(1,i,n)
	{
		ll opt=sum/a[i],x,y;
		Exgcd(opt,a[i],x,y);
		ans=(ans+b[i]*opt*x%sum)%sum;
	}
	wr((ans%sum+sum)%sum),pr;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号