我们知道一个事实,把一个较大的数字转化成数位数组思考,很容易将一个大循环变成很小的循环。
这在解决某些问题的过程中可以发挥很大的作用,将时间压缩。
例子:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1315
一个整数集合S是合法的,指S的任意子集subS有Fun(SubS)!=X,其中X是一个固定整数,Fun(A)的定义如下:
分析:如果直接逐个枚举,那么2^50够我们受的了。但是如果,把那些很大的数字变成数位数组来思考,那么我们可以这样做:将有可能的数字(数字<=X, 且对应的二进制数位上如果X是0,那么该数字也应该是0)转成数位累加起来,最后,数字X二进制位上是1的,累加后的数位数值的最小值就是答案。
例子:
3 7
1 2 4
数位:
1:0 0 1
2:0 1 0
4:1 0 0
累加后:1 1 1
7:1 1 1
最小的数位数值就是1
下面的代码应该不用看了。。。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N=55; int bit[35]; void solve(int a){ int dex=1; while(a){ if(a&1) bit[dex]++; dex++; a>>=1; } } int length(int a){ int ans=0; while(a){ a>>=1; ans++; } return ans; } int main() { int n,x; while(cin>>n>>x){ memset(bit,0,sizeof(bit)); int a; int len=length(x),ans=0x3f3f3f3f; for(int i=1;i<=n;i++){ scanf("%d",&a); if(a<=x) { bool flag=1; for(int i=1;i<=len;i++){ if(!(x&(1<<(i-1)))&&(a&(1<<(i-1)))){ flag=0;break; } } if(flag)solve(a); } } for(int i=1;i<=len;i++){ if(x&(1<<(i-1))){ ans=min(ans,bit[i]); } } printf("%d\n",ans); } return 0; }