Warning: session_start(): open(/tmp/sess_decb8b049a276a0aa0f5dade8b6974d0, O_RDWR) failed: No space left on device (28) in /data/wiki/inc/init.php on line 239

Warning: session_start(): Failed to read session data: files (path: ) in /data/wiki/inc/init.php on line 239

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/auth.php on line 430

Warning: mkdir(): No space left on device in /data/wiki/lib/plugins/dw2pdf/vendor/mpdf/mpdf/src/Cache.php on line 19
Temporary files directory "/data/wiki/data/tmp/dwpdf/469/" is not writable

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/actions.php on line 38

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/lib/tpl/dokuwiki/main.php on line 12
2020-2021:teams:legal_string:jxm2001:数论_5 [CVBB ACM Team]

用户工具

站点工具


2020-2021:teams:legal_string:jxm2001:数论_5

数论 5

卢卡斯定理

算法简介

$O(p+\log_pn)$ 计算 ${n\choose m}\bmod p$ 的算法,$p$ 为素数。

算法实现

$${p\choose i}=\frac pi{p-1\choose i-1}$$

于是对 $1\le i\le p-1$,有 ${p\choose i}\equiv 0\pmod p$。

$$(1+x)^p\equiv {p\choose 0}+{p\choose 1}x+\cdots +{p\choose p}x^p\equiv 1+x^p\pmod p$$

对 ${n\choose m}$,不妨设 $n=k_1p+r_1,m=k_2p+r_2$,于是有

$$(1+x)^n\equiv (1+x)^{k_1p+r_1}\equiv ((1+x)^p)^{k_1}(1+x)^{r_1}\equiv (1+x^p)^{k_1}(1+x)^{r_1}\pmod p$$

对比左右两边 $x_m$ 的系数,有

$${n\choose m}\equiv {k_1\choose k_2}{r_1\choose r_2}\pmod p$$

于是递归处理,有

$$\text{Lucas}(n,m)\equiv \text{Lucas}(\lfloor \frac np\rfloor,\lfloor \frac mp\rfloor){n\bmod p\choose m\bmod p}$$

代码模板

洛谷p3807

查看代码

查看代码

const int MAXN=1e5+5;
int frac[MAXN],invfrac[MAXN];
int quick_pow(int a,int b,int p){
	int ans=1;
	while(b){
		if(b&1)ans=1LL*ans*a%p;
		a=1LL*a*a%p;
		b>>=1;
	}
	return ans;
}
int Lucas(int n,int m,int p){
	if(n<m)return 0;
	else if(n<p)return 1LL*frac[n]*invfrac[n-m]%p*invfrac[m]%p;
	else return 1LL*Lucas(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
int main()
{
	int T=read_int();
	while(T--){
		int n=read_int(),m=read_int(),p=read_int();
		frac[0]=1;
		_for(i,1,p)frac[i]=1LL*frac[i-1]*i%p;
		invfrac[p-1]=quick_pow(frac[p-1],p-2,p);
		for(int i=p-1;i;i--)
		invfrac[i-1]=1LL*invfrac[i]*i%p;
		enter(Lucas(n+m,n,p));
	}
	return 0;
}

拓展卢卡斯

算法简介

$O(\sum p_i^k+\sum \log_{p_i^k}n)$ 计算 ${n\choose m}\bmod p$ 的算法,其中 $p=\prod p_i^k$。

算法实现

2020-2021/teams/legal_string/jxm2001/数论_5.1602829509.txt.gz · 最后更改: 2020/10/16 14:25 由 jxm2001