Codeforces 261C Maxim and Matrix

問題

問題文中の擬似コードにしたがって(m+1)x(m+1)の行列を埋めたとき、
最後の行に現れる1の数がtに等しいようなmのうち、
m≦nを満たすものはいくつあるか求めよ。


行列の埋め方は要約すると以下の通り。
1行目は右上だけを1にする。
a[i][j] = a[i-1][j-1] ^ a[i-1][j+1](ただしはみ出たところは0と考える)

制約条件

n, t≦10^12

方針

実験。
ixiの行列の最後の行の1の数をf(i)として、f(i)を出力してみると、全部2^xになっている。
じゃあ2^xのxだけ出力してみる。


すると、i = 2^k-1のときに必ず0になっていて、
じゃあ1ずらして、iとf(i+1)の表を作ってみると、なんかfはビットカウント-1になっている。


つまり f(i) = 2 ^ (bit(i+1) - 1)


なので、要するにn以下の整数のうち立っているビットの個数が一定の個数の
数は何個か求める問題になって、これは適当に桁DPすればいい。

ソースコード

int m, d[70];
ll dp[70][70][2]; //pos, bit, sml

int main(){
	/*
	int a[500][500];
	a[0][0] = 1;
	for(int i = 1; i < 500; i++) rep(j, i+1){
		if(j == 0) a[i][j] = a[i-1][j+1];
		else if(j == i) a[i][j] = a[i-1][j-1];
		else a[i][j] = a[i-1][j+1] ^ a[i-1][j-1];
	}
	rep(i, 100){
		int s = 0;
		rep(j, i+1) s += a[i][j];
		cerr<<i<<" "<<s<<" "<<__builtin_ctz(s)<<endl;
	}
	f(n) = 1 << (bit(n+1) - 1)
	n+1以下の整数で、tailzero(t)+1とbit数が等しいものを数えればいい
	*/
	
	ll n, t;
	cin >> n >> t;
	n++;
	for(; n; n /= 2) d[m++] = n % 2;
	reverse(d, d + m);
	
	int bit = __builtin_ctzll(t) + 1;
	if(__builtin_popcountll(t) != 1){
		cout << 0 << endl;
		return 0;
	}
	
	dp[0][0][0] = 1;
	rep(i, m) rep(j, i + 1) rep(k, 2) if(dp[i][j][k]){
		rep(l, 2){
			int nk = k || l < d[i];
			if(!nk && l > d[i]) continue;
			dp[i + 1][j + l][nk] += dp[i][j][k];
		}
	}
	cout << dp[m][bit][0] + dp[m][bit][1] - (t == 1) << endl;
	
	return 0;
}