pku 3219 Binomial Coefficients 位运算相关的三种方法

     此题题意很清晰,就是判断二项式系数的奇偶性。这里我介绍此题的三种解法,其中第一种是我自己想的,后面两种是参照别人的!

法一:

题意可以转化为n!/(k!*(n-k)!)中分子与分母2的幂是否相等,如果相等则是奇数,否则为偶数。即转化为求n!中2的幂,根据n的二进制表示(不妨设位为1的数位(右向左从0开始)分别为a[0],a[1]...)可以把n!分成1~1<<a[0], (1<<a[0])+1~(1<<a[0])+1<<a[1],....,对于每一段又分成2的最高次幂为1,2,...,用其乘以元素个数,最后相加即可!

#include <iostream> using namespace std; __int64 exponent(__int64 n) { if(n==0||n==1) return 0; __int64 a[34], i, j, k, sum=0; memset(a, 0, sizeof(a)); k=0; while(n) { a[k++]=n&1;//相当于%2,用位运算快些 n=n>>1; //相当于/2 } for(i=k-1; i>=1; i--) if(a[i]) {//2的最大次幂为j时,个数为1<<i-j-1个 //(可以这样想,i位的前面与j位的后面都已确定, //j-i之间每个位有2种选择) for(j=1; j<i; j++) sum+=j*(1<<(i-j-1)); sum+=i;//最后一个元素,即本身i } return sum; } int main() { __int64 k, n; // freopen("1.txt", "r", stdin); // freopen("2.txt", "w+", stdout); while(scanf("%I64d%I64d", &n, &k)!=EOF) { if(k==0||k==n) { printf("1/n"); continue; } if(exponent(n)-exponent(k)!=exponent(n-k)) printf("0/n"); else printf("1/n"); } // fclose(stdin); // fclose(stdout); return 0; }

法二:

直接统计2的个数!

#include <iostream> using namespace std; int main() { int n, k, a, b, c, m; while(scanf("%d%d", &n, &k)!=EOF) { m=n-k; a=b=c=0; while(n=n>>1) a+=n; while(m=m>>1) b+=m; while(k=k>>1) c+=k; if(a-b>c) printf("0/n"); else printf("1/n"); } return 0; }

法三:

c(n,k)(k<=n)的奇偶性取决于(n-k)与k的二进制表达式是否存在同一位上的两个数码均为1,若存在,则为偶数,反之为奇数
#include<iostream> using namespace std; int main() { int n, k; while(scanf("%d%d", &n, &k)!=EOF) { if(k&(n-k)) printf("0/n"); else printf("1/n"); } return 0; }

你可能感兴趣的:(pku 3219 Binomial Coefficients 位运算相关的三种方法)