zoukankan      html  css  js  c++  java
  • 组合数取模 【数论】

    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    题目:

    3942: 组合数取模

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 113  Solved: 39
    [Submit][Status][Web Board]

    Description

    给出N,M,P,求C(N,M) Mod P
    1<=M<=N<=10^6,1<=P<=10^5,P可能为合数

    Input

    一行给出N,M,P

    Output

    如题

    Sample Input

    5 2 3

    Sample Output

    1

    HINT

    如果直接用公式暴力的话,显然会爆出long long类型,直接RE。

    所以要优化,我们可以利用组合数公式来进一步推倒。

    我们可以将n!写成几个质数幂的积的形式。再利用逆元不断取模即可。

    我们可以先把能约的先约掉,直接指数相减即可。

    例如:5!=1*2*3*4*5   可以写成:(2^3)*(3^1)*(5^1) 又可以写成:(2^3)%p*(3^1)%p*(5^1)%p 即可

    我们可以先用欧拉线筛求出质数,再把质数进行求其指数,最后用快速幂还原成常数即可。

    在上代码之前先来解释一下我的变量:

    Isprime表示质数的顺序。例如:2为所有质数的第一个,所以Isprime[2]==1

    3为所有质数的第二个,所以Isprime[3]==2  ……

    primenum表示在n以内有多少个质数。例如:当n==10时,primenum[10]==4 因为10以内有4个质数。

    sum表示当前质数的指数为多少。例如:2^3 为sum[2]==3

    code:

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(3)
     3 #define int long long
     4 const int N=1e6+10;
     5 using namespace std;
     6 int n,m,p;
     7 int Isprime[N],primenum[N],sum[N];
     8 bool vis[N];
     9 int ans=1;
    10 int tot=0;
    11 void inint(){
    12     freopen("com.in","r",stdin);
    13     freopen("com.out","w",stdout);
    14 }
    15 inline int read(){
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    18     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    19     return x*f;
    20 }
    21 inline void write(int x)
    22 {
    23     if(x<0)x=-x,putchar('-');
    24     if(x>9)write(x/10);
    25     putchar(x%10+'0');
    26 }
    27 int quick_mi(int a,int b){
    28     if(b==0)return 1;
    29     if(b%2==1)return quick_mi(a*a,b/2)*a;
    30     else return quick_mi(a*a,b/2);
    31 }
    32 void PRIME(int x){
    33     for(int i=2;i<=x;i++){
    34         primenum[i]=primenum[i-1];
    35         if(!vis[i]){
    36             Isprime[++tot]=i;
    37             primenum[i]++;
    38         }
    39         for(int j=1;j<=tot&&i*Isprime[j]<=x;j++){
    40             vis[i*Isprime[j]]=true;
    41             if(i%Isprime[j]==0)break;
    42         }
    43     }
    44     return ;
    45 }
    46 void solve(int x,int y,int z,int mod){
    47     for(int i=1;i<=primenum[x];i++){
    48         int yzl=x;
    49         while(yzl!=0){
    50             sum[i]+=yzl/Isprime[i];
    51             yzl=yzl/Isprime[i];
    52         }
    53     }
    54     for(int i=1;i<=primenum[y];i++){
    55         int yzl=y;
    56         while(yzl!=0){
    57             sum[i]-=yzl/Isprime[i];
    58             yzl=yzl/Isprime[i];
    59         }
    60     }
    61     for(int i=1;i<=primenum[z];i++){
    62         int yzl=z;
    63         while(yzl!=0){
    64             sum[i]-=yzl/Isprime[i];
    65             yzl=yzl/Isprime[i];
    66         }
    67     }
    68     for(int i=1;i<=primenum[x];i++){
    69         ans=ans*(quick_mi(Isprime[i],sum[i])%mod);
    70         ans%=mod;
    71     }
    72     return ;
    73 }
    74 signed main()
    75 {
    76     //inint();
    77     n=read(),m=read(),p=read();
    78     PRIME(n);
    79     solve(n,m,n-m,p);
    80     printf("%lld
    ",ans);
    81     return 0;
    82 }
     
  • 相关阅读:
    ios web 媒体查询兼容
    Linux python 虚拟环境管理
    three.js 纹理动画实现
    three.js 在模型上移动相机
    three.js 模型拖动之DragControls控制器
    three.js 添加html内容、文本
    微信公众号对接记录
    事务的日志
    事务的隔离级别
    事务中的锁
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11806228.html
Copyright © 2011-2022 走看看