lucas数论定理学习

来源:互联网 发布:人工智能是怎么来的 编辑:程序博客网 时间:2024/05/28 15:06

2015ICPC长春网络赛1010 考到了lucas+crt(中国剩余定理)

赛后补题ing。。

卢卡斯定理的百度百科

证明来自一本《初等数论》非常赞!


hdu3037

模板题

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cstdlib>#include <set>#include <string>#include <map>#include <queue>//#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 100001;const int mod = 10007;const int inf = 0x7f7f7f7f;const double eps = 1e-4;#define pb push_back#define fi first#define se second#define mp make_pair#define pii pair<int,int>int N, M, P;int aa[maxn];int inv(int n,int p) {    int m=1, k=p-2;    while(k) {        if(k&1) m=1ll*m*n%p;        k>>=1; n=1ll*n*n%p;    }    return m;}int Cm(int n,int m,int p) {    if(m>n) return 0;    return aa[n]*1ll*inv(aa[m],p)*inv(aa[n-m],p)%p;}ll lucas(int n,int m,int p) {    if(!m) return 1;    return lucas(n/p,m/p,p)*Cm(n%p,m%p,p)%p;}int main() {    int T; cin>>T; aa[0]=1;    while(T--) {        scanf("%d%d%d", &N, &M, &P);        for(int i=1;i<P;i++) aa[i]=aa[i-1]*1ll*i%P;        printf("%d\n", (int)lucas(N+M,M,P) );    }    return 0;}


hdu4349

 C(n,0),C(n,1),C(n,2)...C(n,n).里面有几个奇数

对于C(n,m)是否为奇数就是求C(n,m)%2,lucas~

n,m写成2进制:n=a[k]a[k-1]...a[0],m=b[k]b[k-1]...b[0]

如果存在一个a[i]<b[i],则C(n,m)%2=0

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cstdlib>#include <set>#include <string>#include <map>#include <queue>//#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 100001;const int mod = 10007;const int inf = 0x7f7f7f7f;const double eps = 1e-4;#define pb push_back#define fi first#define se second#define mp make_pair#define pii pair<int,int>int N, M, P;int aa[maxn];int inv(int n,int p) {    int m=1, k=p-2;    while(k) {        if(k&1) m=1ll*m*n%p;        k>>=1; n=1ll*n*n%p;    }    return m;}int Cm(int n,int m,int p) {    if(m>n) return 0;    return aa[n]*1ll*inv(aa[m],p)*inv(aa[n-m],p)%p;}ll lucas(int n,int m,int p) {    if(!m) return 1;    return lucas(n/p,m/p,p)*Cm(n%p,m%p,p)%p;}int main() {//    int T; cin>>T;    while(~scanf("%d", &N)) {        ;        M=0;        for(int i=1;i<=N;i<<=1) {            if(N&i) M++;        }        printf("%d\n", 1<<M);    }    return 0;}

hdu 3944


求杨辉三角中从顶点到(n,k)路径和(只能向下或右下,如图)的 路径和的最小值 mod p

例如样例4 2 路径为 (0,0) -> (2,0) -> (4,2)

只考虑终点在左半边的情况,对称可以求右半边

先是路径肯定是直线下降,然后一直右下到达终点,显然这种路只有一条

下降的部分全部为1

右下的部分为 (n-m,0) -> (n,m)

C(n-m,0) + ... + C(n,m)=C(n+1,m)

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cstdlib>#include <set>#include <string>#include <map>#include <queue>//#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 10001;const int mod = 10007;const int inf = 0x7f7f7f7f;const double eps = 1e-4;#define pb push_back#define fi first#define se second#define mp make_pair#define pii pair<int,int>int N, M, P, K;//int aa[maxn];int aap[1230][maxn];int inv(int n,int p) {    int m=1, k=p-2;    while(k) {        if(k&1) m=m*n%p;        k>>=1; n=n*n%p;    }    return m;}int Cm( int n,int m,int p) {    if(m>n) return 0;    return aap[K][n]*1ll*inv(aap[K][m],p)*inv(aap[K][n-m],p)%p;}int lucas(int n,int m,int p) {    if(!m) return 1;    return lucas(n/p,m/p,p)*Cm(n%p,m%p,p)%p;}int prim[maxn];int main() {//    int T; cin>>T;    for(int i=2;i<maxn;i++) {        if(!prim[i]) {            prim[++prim[0]]=i;            for(int j=2;i*j<maxn;j++) prim[i*j]=1;            int p=prim[0];            aap[p][0]=1;            for(int j=1;j<i;j++) aap[p][j]=aap[p][j-1]*j%i;        }    }    int kase=1;    while(~scanf("%d%d%d", &N, &M, &P)) {        printf("Case #%d: ", kase++ );        if(2*M>N) M=N-M;        K=lower_bound(prim+1,prim+prim[0],P)-prim;        printf("%d\n", (lucas(N+1,M,P)+N-M)%P );    }    return 0;}



0 0
原创粉丝点击