首先給出這個lucas定理:
a、b是非負整數,p是質數。ab寫成p進製:a=a[n]a[n-1]...a[0],b=b[n]b[n-1]...b[0]。
則組合數c(a,b)與c(a[n],b[n])*c(a[n-1],b[n-1])*...*c(a[0],b[0]) modp同餘
即:lucas(n,m,p)=c(n%p,m%p)*lucas(n/p,m/p,p)
這個定理的證明不是很簡單,我一直想找個很好的張明,但是,沒找到,昨天看到了乙個解題報告,基本上可以說明白這個lucas定理是怎麼回事了,具體的是說:
以求解n! % p為例,把n分段,每p個一段,每一段求的結果是一樣的。但是需要單獨處理每一段的末尾p, 2p, ...,把p提取出來,會發現剩下的數正好又是(n / p)!,相當於劃歸成了乙個子問題,這樣遞迴求解即可。
這個是單獨處理n!的情況,當然c(n,m)就是n!/(m!*(n-m)!),每乙個階乘都用上面的方法處理的話,就是lucas定理了,注意這兒的p是素數是有必要的。
lucas最大的資料處理能力是p在10^5左右,不能再大了,hdu 3037就是10^5級別的!
對於大組合數取模,n,m不大於10^5的話,用逆元的方法,可以解決。對於n,m大於10^5的話,那麼要求p<10^5,這樣就是lucas定理了,將n,m轉化到10^5以內解。
然後再大的資料,我就不會了!
貼乙個例題的**,方便以後看。
hdu 3037
將不大於m顆種子存放在n顆樹中,問有多少種存法。
首先是不大於m顆種子,我沒可以認為少於m的那些種子存放在了第n+1顆樹上,這樣的話,問題就轉化成了將m顆種子存放在n+1顆樹上的方案數。ok這個是組合數學裡面的公式,亦即插板法,也就是x1+x2+x3+……+xn+1 = m;ok,答案是c(n+m,m);
然後就是上面說的lucas定理解決大組合數問題了
#include #include #include using namespace std;
#define n 100010
long long mod_pow(int a,int n,int p)
return ret;
}long long factorial[n];
void init(long long p)
long long lucas(long long a,long long k,long long p) //求c(n,m)%p p最大為10^5。a,b可以很大!
return re;
}int main()
return 0;
}
Lucas定理 組合數取模
a b是非負整數,p是質數。ab寫成p進製 a a n a n 1 a 0 b b n b n 1 b 0 則組合數c a,b 與c a n b n c a n 1 b n 1 c a 0 b 0 modp同餘 即 lucas n,m,p c n p,m p lucas n p,m p,p 然而如果...
Lucas定理與大組合數的取模的求法總結
首先給出這個lucas定理 a b是非負整數,p是質數。ab寫成p進製 a a n a n 1 a 0 b b n b n 1 b 0 則組合數c a,b 與c a n b n c a n 1 b n 1 c a 0 b 0 modp同餘 即 lucas n,m,p c n p,m p lucas ...
Lucas定理應用分析 大組合數取模
首先給出lucas 盧卡斯 定理 有非負整數a b,和素數p,a b寫成p進製為 a a n a n 1 a 0 b b n b n 1 b 0 則組合數c a,b 與 c a n b n c a n 1 b n 1 c a 0 b 0 mod p同餘。即 lucas n,m,p c n p,m p...