Google Code Jam Japan Qual C: ビット数
問題概要
a + b = N(<10^12)を満たすようにpopcount(A) + popcount(B)を最大化する問題。
考えたこと
- とりあえずsmallは本当に書くだけなのでさっさと書く。
- Dに64ビットのpopcntが無かったので真面目に書く。
- largeを考えよう。こういうのは大抵桁でDPだ。
- でももっと楽に行けそう。片方は111..11になるように仮定して良さそう。
- もう少し真面目に考えると、基本的に立っている方のビットは片方に押し付けて良いし、途中に両方ビットが0になってるようなものがあれば上のビットから1を借りてきて今のビットで1,1に分けた方が良い。
- やっぱり64ビットでのcountLeadingZero的なものはないので愚直に全通り試す。計算量は落ちるけど十分。
通ったコード
small
import std.stdio; import std.algorithm; int nextInt(){ int x; scanf("%d",&x); return x; } int popCount(long x){ int ret = 0; for( ; x > 0 ; x>>=1){ ret += x&1; } return ret; } int solve(long x){ int ret = 0; for(auto i = 0; i <= x; i++){ ret = max(ret, popCount(i) + popCount(x-i)); } return ret; } void main(){ for(auto c = 1, T = nextInt; c <= T; c++){ writef("Case #%d: %d\n", c, solve(nextInt)); } }
large
import std.stdio; import std.stream; import std.algorithm; long nextLong(){ long x; scanf("%lld", &x); return x; } int popCount(ulong x){ int ret = 0; for( ; x > 0 ; x>>=1){ ret += x&1; } return ret; } int solve(ulong x){ int ret = 0; for(int i = 0; i<63; i++){ auto y = (1L<<i)-1; if(x >= y){ ret = max(ret, popCount(x - y) + popCount(y)); } } return ret; } void main(){ for(auto c = 1, T = nextLong; c <= T; c++){ writef("Case #%s: %s\n", c, solve(nextLong)); } }