对于本题,由于访问的次数很大,所以当然得先预处理保存在数组中,然后用的时候就不用一次一次的再重复计算了,本题重在预处理。
- #include <stdio.h>
- #include <string.h>
- #define N 10005
- int p;
- int prim[N];
- int pth[N];
- int inv[N][N];
- bool prime[N];
- int fac[N][N];
- int k=0;
- void isprime()
- {
- int i,j;
- memset(prime,true,sizeof(prime));
- memset(pth,0,sizeof(pth));
- for(i=2;i<N;i++)
- {
- if(prime[i])
- {
- prim[++k]=i;
- pth[i]=k;
- for(j=i+i;j<N;j+=i)
- {
- prime[j]=false;
- }
- }
- }
- }
- int quick_mod(int a,int b,int m)
- {
- int ans=1;
- a%=m;
- while(b)
- {
- if(b&1)
- {
- ans=ans*a%m;
- b--;
- }
- b>>=1;
- a=a*a%m;
- }
- return ans;
- }
- void init()
- {
- int i,j;
- for(int i=1;i<=k;i++)
- {
- fac[i][0]=inv[i][0]=1;
- for(j=1;j<prim[i];j++)
- {
- fac[i][j]=(fac[i][j-1]*j)%prim[i];
- inv[i][j]=quick_mod(fac[i][j],prim[i]-2,prim[i]);
- }
- }
- }
- int C(int n,int m)
- {
- if(m>n) return 0;
- if(m==n) return 1;
- int t=pth[p];
- return fac[t][n]*(inv[t][n-m]*inv[t][m]%p)%p;
- }
- int Lucas(int n,int m)
- {
- if(m==0) return 1;
- return C(n%p,m%p)*Lucas(n/p,m/p)%p;
- }
- int main()
- {
- int n,m,k=1;
- isprime();
- init();
- while(~scanf("%d%d%d",&n,&m,&p))
- {
- if(m<=n/2) m=n-m;
- printf("Case #%d: %d\n",k++,(m%p+Lucas(n+1,m+1)%p)%p);
- }
- return 0;
- }
-
对于组合数C(n,m),我们想知道他为奇数还是偶数,当然我们有(n&k)==k这个神器,但是用这个就得枚举,如果数太大果断超时,比如HDU4349题,就是
说C(n,0),C(n,1),....C(n,n)中奇数有多少个,n范围是10^8,这里就用了Lucas定理了。
对于n,m根据Lucas定理,我们先把他们转化为二进制,这样n,m都是01序列了。
这样我们可以看出C(0,1)=0,C(0,0)=1,C(1,0)=1,C(1,1)=1,这样n中为0的地方对应的m中的位置我们只有一种可能,那就是0,不然C(n,m)就成0了,所以
这样我们可以不用管n中为0的地方,只考虑n中为1的位置,当然很明显可以看出,n中为1的位置对应的m中为0或1,其结果都是1,所以这样一来答案就直
接相当于是1<<(n中1的个数)了。
其实除了这样,直接找规律也是可以的,只是那样很麻烦,不容易看出来。然后我们现在就可以将看似很难的HDU4349水之了。
其实关于(n&k)==k的证明也就很容易了,同样的方法利用Lucas啊。。。
- #include <stdio.h>
- int main()
- {
- int n;
- while (~scanf("%d",&n))
- {
- int count = 0;
- while (n)
- {
- if (n&1) count++;
- n>>=1;
- }
- printf("%d\n",1<<count);
- }
- return 0;
- }
注意(n&k)==k与n&k==k不一样。
- #include <stdio.h>
- int main()
- {
- int n,k;
- while(~scanf("%d%d",&n,&k))
- {
- if((n&k)==k)
- {
- printf("1\n");
- }
- else
- {
- printf("0\n");
- }
- }
- return 0;
- }