zoukankan      html  css  js  c++  java
  • P3807【模板】卢卡斯定理

    题解大部分都是递归实现的,给出一种非递归的形式
    话说上课老师讲的时候没给代码,然后自己些就写成了这样

    对于质数\(p\)给出卢卡斯定理:

    \[\tbinom{n}{m}=\tbinom{n \bmod p}{m \bmod p}\tbinom{\lfloor \frac{n}{p}\rfloor}{\lfloor \frac{m}{p} \rfloor}\pmod p \]

    其实它还有另一种形式,虽然本质上没啥区别:

    \[\tbinom{n}{m}=\prod_{i=1}^k \tbinom{a_i}{b_i} \pmod p \]

    其中,\(a,b\)分别为\(n,m\)\(p\)进制下的每一位,\(k\)是它们位数的较大值,当然如果有数不足\(k\)位,要补前导0


    来证明一下
    其实证明方法也是看了别人blog才知道的
    \(s=\lfloor \dfrac{n}{p}\rfloor,t=\lfloor \dfrac{m}{p}\rfloor\)
    则有\(q,w\)使得\(n=sp+q,m=tp+w\)
    再考虑一个二项式:

    \[(1+x)^n=((1+x)^p)^s(1+x)^q \]

     
    先由费马小定理推个结论:

    \[x^p\equiv x\pmod p \Rightarrow (x^p+1)\equiv (x+1)\pmod p \]

    \[(x+1)^p\equiv (x+1)\pmod p \]

    所以:

    \[(x+1)^p\equiv (x^p+1)\pmod p \]

     
    把这个结论带进去:

    \[(1+x)^n\equiv (1+x^p)^s(1+x)^q \pmod p \]

    再由二项式定理把右边展开

    \[(1+x)^n\equiv \sum_{i=1}^s \tbinom{s}{i}x^{pi}\cdot \sum_{j=1}^q \tbinom{q}{j}x^j \]

    同样我们可以把左边展开:

    \[(1+x)^n=\sum_{i=1}^{sp+q}\tbinom{sp+q}{i}x^i \]

    然后我们可以发现,左右两遍都有\(x^{tp+w}\)次项(当然,这是在\(m\leq n\)的情形下,如果\(m>n\)结果就是0,不用考虑了)
    比较一下它们的系数
    左边:\(\tbinom{sp+q}{tp+w}x^{tp+w}\)
    右边:\(\tbinom{s}{t}x^{tp}\cdot \tbinom{q}{w}x^w\)
    这边要说明一下,不会出现别的次数组合,比如\((t-1)p\)\((w+p)\),因为\(w,q<p\)
    所以:\(\tbinom{sp+q}{tp+w}\equiv \tbinom{s}{t}\tbinom{q}{w}\pmod p\)
    即:

    \[\tbinom{n}{m}\equiv\tbinom{n \bmod p}{m \bmod p}\tbinom{\lfloor \frac{n}{p}\rfloor}{\lfloor \frac{m}{p} \rfloor}\pmod p \]

    然后把\(\tbinom{\lfloor \frac{n}{p}\rfloor}{\lfloor \frac{m}{p} \rfloor}\)这一项不断展开,其实就变为了那种非递归形式


    好了,我们终于得到了这个定理
    那写代码就简单了,将\(n,m\)转化为\(p\)进制
    预处理出阶乘数组,和阶乘的逆元数组
    然后对于这\(p\)进制的每一位直接套组合数公式就行了
    然而代码似乎没有递归的好写
    另外一共5个点,我错了三遍下载了三个数据来调
    那么说一下踩得坑,首先主函数for循环里的特判一定要有,避免出现数组下标变成负数,或者使用0的逆元的情况
    还有多测时前导0的位置一定要清零

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #include<stack>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n,m,p;
    LL fac[200006],g[200006];
    int a[100006],b[100006];
    inline LL power(LL x,LL y){
    	reg LL ans=1;
    	while(y){
    		if(y&1) ans=(1ll*ans*x)%p;
    		y>>=1;x=(x*x*1ll)%p;
    	}
    	return ans;
    }
    std::stack<int>s;
    inline void pre(){//预处理函数
    	a[0]=b[0]=0;
    	while(n){
    		s.push(n%p);n/=p;
    	}
    	while(!s.empty()) a[++a[0]]=s.top(),s.pop();
    	int tmp=0;
    	while(m){
    		tmp++;
    		s.push(m%p);m/=p;
    	}
    	while(b[0]+tmp<a[0]) b[++b[0]]=0;//前导零的位置一定要清零 
    	while(!s.empty()) b[++b[0]]=s.top(),s.pop();
    	fac[0]=1;
    	for(reg int i=1;i<p;i++) fac[i]=(1ll*fac[i-1]*i)%p;
    	g[p-1]=power(fac[p-1],p-2);
    	for(reg int i=p-2;i;i--) g[i]=(1ll*g[i+1]*(i+1))%p;
    }
    int main(){int t=read();while(t--){
    	n=read();m=read();p=read();
    	n+=m;m=n-m;
    //	std::memset(a,0,sizeof a);std::memset(b,0,sizeof b);
    	pre();
    //		for(reg int i=1;i<=a[0];i++) std::printf("%d ",a[i]);EN;
    //		for(reg int i=1;i<=b[0];i++) std::printf("%d ",b[i]);EN;
    //		for(reg int i=0;i<p;i++) std::printf("%d ",fac[i]);EN;
    //		for(reg int i=0;i<p;i++) std::printf("%d ",g[i]);EN;
    	LL ans=1;
    //		std::printf("%d %d\n",a[0],b[0]);
    	for(reg int i=1;i<=a[0];i++){
    		if(!b[i]) continue;
    		if(a[i]<b[i]){ans=0;break;}
    		if(a[i]==b[i]) continue;
    		ans=(1ll*ans*fac[a[i]])%p;
    		ans=(1ll*ans*g[b[i]])%p;
    		ans=(1ll*ans*g[a[i]-b[i]])%p;
    	}
    	std::printf("%lld\n",ans);
    }
    	return 0;
    }
    
  • 相关阅读:
    Effective C++笔记_条款25考虑写出一个不抛出异常的swap函数
    SilverLight小游戏
    可分片数据持久层ShardingPL使用说明
    r.a.d controls 学习笔记 - radcombobox + RadWindowManager 组成的参照控件
    用 .Net Remoting 技术实现“定向广播”
    Silverlight中的资源文件
    一个丑陋的对Silverlight中的Grid无CellPadding的解决方案
    几个小问题
    .Net Remoting 排错笔记:An existing connection was forcibly closed by the remote host
    .Net Remoting 排错笔记:The constructor to deserialize an object of type 'xxx.xxxx.xxxxx' was not found.
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12527265.html
Copyright © 2011-2022 走看看