• comb


    Problem 3. comb
    一天,Mr. Ding 对组合数产生了兴趣,他想要知道满足下面条件的数i 有多少个:

    gcd=( C( n , i )  ,  p )  =  p ;

    其中p 是素数。
    Input
    第1 行,2 个整数:n p。
    Output
    输出所求。
    Sample
    comb.in comb.out
    5 2 2
    Note
    样例中,一共有6 个组合数:1; 5; 10; 10; 5; 1,其中和2 公约数为2 的数有两个10,故输出2。
    • 对于30% 的数据,满足1<=n,p <=10^3
    • 对于100% 的数据,满足1<=n, p <= 10^18

    题解:

    首先看到条件gcd( C (  n ,i ),p )=p,所以由此我们可以得到这样一个事实: p | C (  n  , i  ) ---- C (  n , i  ) % p =0

    由于p是一个素数,所以可以通过Lucas对其进行分解,则可以得到 p | C (  n1 , i1  ) C (  n2 , i2  ) .....C (  nk , ik  ) , 我们知道Lucas中满足当n<i时 C (  n , i  ) = 0 ,所以我们很难确定在p | C (  n1 , i1  ) C (  n2 , i2  ) .....C (  nk , ik  ) 中是哪一个组合数为0, 所以我们不妨换一个思路,因为p ∤ C (  n1 , i1  ) C (  n2 , i2  ) .....C (  nk , ik  )很好求,我们求出满足p ∤ C (  n1 , i1  ) C (  n2 , i2  ) .....C (  nk , ik  )的i的个数,再用( n+1 )减去这个个数就可以得到题上所求。

    所以现在我们来想一想该怎么求这个个数:

    首先我们知道n1,n2·····nk以及i1,i2·····ik都是小于p的,所以可以将所有的n以及i首尾相连想成两个p进制的数,所以只有C (  n1 , i1  ) C (  n2 , i2  ) .....C (  nk , ik  ) 每一项都非0才满足条件,所以可以得到0<=i<=n,举个例子,C ( 11 , i )可以分解为C (  2 , i1  ) , C (  0 , i2  ) , C (  1 , i3  ) , 所以i1有三种取法0,1,2,而i2有一种0 ,i3有两种0 ,1 ,所以一共要求的有3*2*1=6中,所以答案11+1-6=6 。总结一下就是 (  n+1  ) - (  n1+1  )(  n2+1  ).....(  nk+1  ).

    代码如下:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    
    int tot;
    long long f[10001],n,p;
    
    int main(){
      freopen("comb.in","r",stdin);
      freopen("comb.out","w",stdout);
      scanf("%I64d%I64d",&n,&p);
      long long k=n;
      while (k!=0){
          f[++tot]=k%p;
          k/=p;
      }
      long long h=1;
      for (int i=1;i<=tot;i++)
        h*=(f[i]+1);
      printf("%I64d",(n+1)-h);
      return 0;
    }
  • 相关阅读:
    【转】【矩阵】坐标的矩阵变换
    cocos2d-x聊天气泡
    lua自用的函数收集
    lua错误收集
    cocos2d-x中CCEditbox导出到lua
    love2d杂记9--光照效果
    (转)love2d有用的辅助库--gamework
    XPath语法 在C#中使用XPath示例
    WCF的CommunicationObjectFaultedException异常问题
    WCF绑定(Binding)
  • 原文地址:https://www.cnblogs.com/ganster/p/8446742.html
Copyright © 2020-2023  润新知