hdu3944(Lucas定理+预处理)

来源:互联网 发布:节假日堵车数据 编辑:程序博客网 时间:2024/06/05 15:39
 

hdu3944(Lucas定理+预处理)

分类: 数论 50人阅读 评论(0) 收藏 举报

题目:DP?

 

对于本题,由于访问的次数很大,所以当然得先预处理保存在数组中,然后用的时候就不用一次一次的再重复计算了,本题重在预处理。

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #define N 10005  
  4.   
  5. int p;  
  6.   
  7. int prim[N];  
  8.   
  9. int pth[N];  
  10.   
  11. int inv[N][N];  
  12.   
  13. bool prime[N];  
  14.   
  15. int fac[N][N];  
  16.   
  17. int k=0;  
  18.   
  19. void isprime()  
  20. {  
  21.     int i,j;  
  22.     memset(prime,true,sizeof(prime));  
  23.     memset(pth,0,sizeof(pth));  
  24.     for(i=2;i<N;i++)  
  25.     {  
  26.         if(prime[i])  
  27.         {  
  28.             prim[++k]=i;  
  29.             pth[i]=k;  
  30.             for(j=i+i;j<N;j+=i)  
  31.             {  
  32.                 prime[j]=false;  
  33.             }  
  34.         }  
  35.     }  
  36. }  
  37.   
  38. int quick_mod(int a,int b,int m)  
  39. {  
  40.     int ans=1;  
  41.     a%=m;  
  42.     while(b)  
  43.     {  
  44.         if(b&1)  
  45.         {  
  46.             ans=ans*a%m;  
  47.             b--;  
  48.         }  
  49.         b>>=1;  
  50.         a=a*a%m;  
  51.     }  
  52.     return ans;  
  53. }  
  54.   
  55. void init()  
  56. {  
  57.     int i,j;  
  58.     for(int i=1;i<=k;i++)  
  59.     {  
  60.         fac[i][0]=inv[i][0]=1;  
  61.         for(j=1;j<prim[i];j++)  
  62.         {  
  63.             fac[i][j]=(fac[i][j-1]*j)%prim[i];  
  64.             inv[i][j]=quick_mod(fac[i][j],prim[i]-2,prim[i]);  
  65.         }  
  66.     }  
  67.   
  68. }  
  69.   
  70. int C(int n,int m)  
  71. {  
  72.     if(m>n) return 0;  
  73.     if(m==n) return 1;  
  74.     int t=pth[p];  
  75.     return fac[t][n]*(inv[t][n-m]*inv[t][m]%p)%p;  
  76. }  
  77.   
  78. int Lucas(int n,int m)  
  79. {  
  80.     if(m==0)  return 1;  
  81.     return C(n%p,m%p)*Lucas(n/p,m/p)%p;  
  82. }  
  83.   
  84. int main()  
  85. {  
  86.     int n,m,k=1;  
  87.     isprime();  
  88.     init();  
  89.     while(~scanf("%d%d%d",&n,&m,&p))  
  90.     {  
  91.         if(m<=n/2) m=n-m;  
  92.         printf("Case #%d: %d\n",k++,(m%p+Lucas(n+1,m+1)%p)%p);  
  93.     }  
  94.     return 0;  
  95. }
  96.  

    利用Lucas定理再论组合数奇偶性

    分类: 数论 56人阅读 评论(0) 收藏 举报

    对于组合数C(n,m),我们想知道他为奇数还是偶数,当然我们有(n&k)==k这个神器,但是用这个就得枚举,如果数太大果断超时,比如HDU4349题,就是

    C(n,0)C(n,1)....C(n,n)中奇数有多少个,n范围是10^8,这里就用了Lucas定理了。

    对于nm根据Lucas定理,我们先把他们转化为二进制,这样nm都是01序列了。

    这样我们可以看出C(0,1)=0C(0,0)=1C(1,0)=1C(1,1)=1,这样n中为0的地方对应的m中的位置我们只有一种可能,那就是0,不然C(n,m)就成0了,所以

    样我们可以不用管n中为0的地方,只考虑n中为1的位置,当然很明显可以看出,n中为1的位置对应的m中为01,其结果都是1,所以这样一来答案就直

    相当于是1<<(n1的个数)了。

    其实除了这样,直接找规律也是可以的,只是那样很麻烦,不容易看出来。然后我们现在就可以将看似很难的HDU4349水之了。

    其实关于(n&k)==k的证明也就很容易了,同样的方法利用Lucas啊。。。

     

    题目1:Xiao Ming's Hope

    [cpp] view plaincopy
    1. #include <stdio.h>  
    2.   
    3. int main()  
    4. {  
    5.     int n;  
    6.     while (~scanf("%d",&n))  
    7.     {  
    8.         int count = 0;  
    9.         while (n)  
    10.         {  
    11.             if (n&1) count++;  
    12.             n>>=1;  
    13.         }  
    14.         printf("%d\n",1<<count);  
    15.     }  
    16.     return 0;  
    17. }  


     题目2:Binomial Coefficients

     

    注意(n&k)==k与n&k==k不一样。

    [cpp] view plaincopy
    1. #include <stdio.h>  
    2. int main()  
    3. {  
    4.     int n,k;  
    5.     while(~scanf("%d%d",&n,&k))  
    6.     {  
    7.         if((n&k)==k)  
    8.         {  
    9.             printf("1\n");  
    10.         }  
    11.         else  
    12.         {  
    13.             printf("0\n");  
    14.         }  
    15.     }  
    16.     return 0;  
    17. }  

原创粉丝点击