博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【EXLUCAS模板】【拓展卢卡斯详解】【组合数高级篇】LuoGu P4720
阅读量:5751 次
发布时间:2019-06-18

本文共 5793 字,大约阅读时间需要 19 分钟。

这个东西呢,需要中国剩余定理定理(crt)和拓展欧几里得(exgcd)组合数还有逆元的知识

我们要求的呢,就是这个东西\[C_n^m\% p\]

这里P不一定是质数

1.将P质因数分解

\[p = \prod\limits_{\rm{i}}^r {P_{}^{
{c_i}}} \]

对下面这个进行中国剩余定理合并,便是答案

\[\begin{array}{l}

\begin{array}{*{20}{l}}
{
{x_1} \equiv C_n^m(\,\bmod \,p_1^{
{c_1}})}\\
{
{x_2} \equiv C_n^m(\,\bmod \,p_2^{
{c_2}})}\\
{
{x_3} \equiv C_n^m(\,\bmod \,p_3^{
{c_3}})}
\end{array}\\
\cdot \cdot \cdot \\
{x_r} \equiv C_n^m(\,\bmod \,p_r^{
{c_r}})
\end{array}\]

2.求$C_n^m\% {p^k}$

这个该怎么求呢,但是很明显这个求不了逆元,因为分母的两个数和模数不互质,那么只要把所有的模数因子全部干掉就好了,这样就能求逆元了

也就是这样\[C_n^m\% {p^k} = \frac{

{\frac{
{n!}}{
{
{p^{
{a_1}}}}}}}{
{\frac{
{m!}}{
{
{p^{
{a_2}}}}}*\frac{
{(n - m)!}}{
{
{p^{
{a_3}}}}}}}*{p^{
{a_1} - {a_2} - {a_3}}}\% {p^k}\]

但是这里的$a1a2a3$是不知道的,没事我们看下一步就知道了

3.求$n!\% {p^k}$

我们来举个栗子

\[\begin{array}{l}

22!\% {3^2} = (1*2*3*4*5*6*7*8*9*10*11*12*13*14*14*16*17*18*19*20*21*22)\% {3^2}\\
= (3*6*9*12*15*18*21)*(1*2*4*5*7*8)*(10*11*13*14*16*17)*(19*20*22)\% {3^2}\\
= {3^7}*7!*{(1*2*4*5*7*8)^2}\% {3^2}
\end{array}\]

我们推广一下\[n!\% {p^k} = {p^{n/p}}*(n/p)!*{(\prod\limits_1^{ <  = {p^k}} {nu{m_i}} )^{n/{p^k}}}*(\prod\limits_1^{p\% k} {nu{m_i}} )\% {p^k}\]

看到$(n/p)!$,这个很明显可以递归来解决(注意边界是$n=1||n=2$时候返回值是1)

看到那个${p^{n/p}}$这不就是第二步里没解决的a值吗,对,就是$n/p$;

看那个${(\prod\limits_1^{ <  = {p^k}} {nu{m_i}} )^{n/{p^k}}}$,这个只要写一个循环,计算出一个循环节,然后再快速幂即可;

看那个$(\prod\limits_1^{p\% k} {nu{m_i}} )$这个是冗余,写个循环就可以计算

但是$n/p$很明显是递归的,这个应该怎么解决,写个循环每次都除,再累加就好了

就是这样

1 lt fac(const lt n,const lt pi,const lt pk)//n! % pi^ki pk=pi^ki 2 { 3     if(n==1||n==0)return 1; 4     lt ans=1; 5     for(rt i=2;i

那么第二步的a解决之后,第二步也很好办了

1 lt C(const lt n,const lt m,const lt pi,const lt pk)////C(n,m)%pk  pk=pi^ki2 {3     lt up=fac(n,pi,pk),dl=fac(m,pi,pk),dr=fac(n-m,pi,pk),kk=0;4     for(rt i=n;i;i/=pi)kk+=i/pi;5     for(rt i=m;i;i/=pi)kk-=i/pi;6     for(rt i=n-m;i;i/=pi)kk-=i/pi;7     return up*inv(dl,pk)%pk*inv(dr,pk)%pk*ksm(pi,kk,pk)%pk;8 }

然后我进行了一些基本函数丧心病狂的封装23333

1 namespace basic 2 { 3     inline lt read() 4     { 5         rt x = 0; char zf = 1; char ch; 6         while (ch != '-' && !isdigit(ch)) ch = getchar(); 7         if (ch == '-') zf = -1, ch = getchar(); 8         while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf; 9     }10     void write(lt x)11     {12         if (x<0)putchar('-'),x=-x;13         if (x>9) write(x/10);14         putchar(x%10+'0');15     }16     inline void writeln(const lt x){write(x);putchar('\n');}17     lt gcd(lt a,lt b){
return b?gcd(b,a%b):a;}18 lt ksc(lt a,lt b,lt mod)19 {20 lt fina=0,kk=1;21 if(a<0)a=-a,kk=-kk;if(b<0)b=-b,kk=-kk;22 while(b)23 {24 if(b%2)fina=(fina+a)%mod;25 a=(a+a)%mod,b>>=1;26 }27 return fina%mod*kk;28 }29 lt ksm(lt a,lt k,lt mod)30 {31 if(!k)return 1;32 lt fina=1;33 while(k)34 {35 if(k%2)fina=ksc(fina,a,mod);36 a=a*a%mod,k>>=1;37 }38 return fina%mod;39 }40 void ex_gcd(lt a,lt b,lt &x,lt &y)41 {42 if(!b)x=1,y=0;43 else44 {45 ex_gcd(b,a%b,x,y);lt tt=x;x=y,y=tt-a/b*x;46 }47 }48 lt exgcd(lt a,lt b,lt c)//ax=c(mod b)49 {50 lt gc=gcd(a,b),x=0,y=0;;51 if(c%gc)return -1;52 a/=gc,b/=gc,c/=gc;53 ex_gcd(a,b,x,y);54 return (x*c%b+b)%b;55 }56 inline lt inv(lt a,lt p)57 {58 if(!a)return 0;59 return exgcd(a,p,1);60 }//ax=1(mod p)61 }

然后lucas部分

1 namespace lucas 2 { 3     using namespace basic; 4     lt fac(const lt n,const lt pi,const lt pk)//n! % pi^ki pk=pi^ki 5     { 6         if(n==1||n==0)return 1; 7         lt ans=1; 8         for(rt i=2;i

完整代码

1 #include
2 #include
3 #include
4 #include
5 typedef long long lt; 6 #define rt register lt 7 using namespace std; 8 lt n,m,p,P; 9 namespace basic 10 { 11 inline lt read() 12 { 13 rt x = 0; char zf = 1; char ch; 14 while (ch != '-' && !isdigit(ch)) ch = getchar(); 15 if (ch == '-') zf = -1, ch = getchar(); 16 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf; 17 } 18 void write(lt x) 19 { 20 if (x<0)putchar('-'),x=-x; 21 if (x>9) write(x/10); 22 putchar(x%10+'0'); 23 } 24 inline void writeln(const lt x){write(x);putchar('\n');} 25 lt gcd(lt a,lt b){
return b?gcd(b,a%b):a;} 26 lt ksc(lt a,lt b,lt mod) 27 { 28 lt fina=0,kk=1; 29 if(a<0)a=-a,kk=-kk;if(b<0)b=-b,kk=-kk; 30 while(b) 31 { 32 if(b%2)fina=(fina+a)%mod; 33 a=(a+a)%mod,b>>=1; 34 } 35 return fina%mod*kk; 36 } 37 lt ksm(lt a,lt k,lt mod) 38 { 39 if(!k)return 1; 40 lt fina=1; 41 while(k) 42 { 43 if(k%2)fina=ksc(fina,a,mod); 44 a=a*a%mod,k>>=1; 45 } 46 return fina%mod; 47 } 48 void ex_gcd(lt a,lt b,lt &x,lt &y) 49 { 50 if(!b)x=1,y=0; 51 else 52 { 53 ex_gcd(b,a%b,x,y);lt tt=x;x=y,y=tt-a/b*x; 54 } 55 } 56 lt exgcd(lt a,lt b,lt c)//ax=c(mod b) 57 { 58 lt gc=gcd(a,b),x=0,y=0;; 59 if(c%gc)return -1; 60 a/=gc,b/=gc,c/=gc; 61 ex_gcd(a,b,x,y); 62 return (x*c%b+b)%b; 63 } 64 inline lt inv(lt a,lt p) 65 { 66 if(!a)return 0; 67 return exgcd(a,p,1); 68 }//ax=1(mod p) 69 } 70 namespace lucas 71 { 72 using namespace basic; 73 lt fac(const lt n,const lt pi,const lt pk)//n! % pi^ki pk=pi^ki 74 { 75 if(n==1||n==0)return 1; 76 lt ans=1; 77 for(rt i=2;i

 

转载于:https://www.cnblogs.com/Qin-Wei-Kai/p/10090972.html

你可能感兴趣的文章
Struts2 学习小结
查看>>
在 Linux 系统中安装Load Generator ,并在windows 调用
查看>>
/etc/resolv.conf文件详解
查看>>
Django_4_视图
查看>>
Linux的netstat命令使用
查看>>
IntelliJ IDEA 连接数据库详细过程
查看>>
android学习笔记——onSaveInstanceState的使用
查看>>
工作中如何做好技术积累
查看>>
apache安装报错undefined reference ssl
查看>>
关于爱情只有一句忠告
查看>>
F#初学笔记06
查看>>
实战:将企业域名解析委派给企业DNS服务器
查看>>
在Lync 2013环境部署Office Web Apps
查看>>
微软大会Ignite,你准备好了么?
查看>>
读书笔记-高标管事 低调管人
查看>>
Master带给世界的思考:是“失控”还是进化
查看>>
用户和开发者不满苹果iCloud问题多多
查看>>
java.lang.UnsatisfiedLinkError:no dll in java.library.path终极解决之道
查看>>
我的工具:文本转音频文件
查看>>
【许晓笛】从零开始运行EOS系统
查看>>