一个数变成他的二进制表示中的一的个数
6->2->1
问2^1000以下所有数中,可以进行这个操作k次的数有多少个.
找到每个数需要几次的思路是容易的,问题是这个组合数的计算过程
1,有自己和没自己,0则直接没自己
#include <iostream>
#include <vector>
#include <cmath>
#include <cstring>
#include <bitset>
#include <algorithm>
using namespace std;
#define debug(x) std::cerr << #x << " = " << (x) << std::endl
typedef long long LL;
const int MAXN = 1e3+17;
const int MOD = 1e9+7;
int down[MAXN],tms[MAXN];
string str;
LL C[MAXN][MAXN];
inline void upd(LL & a,LL b)
{
a = (a+b)%MOD;
}
void comb(LL n, LL m, LL p)
{
memset(C, 0, sizeof(C));
C[0][0] = 1;
for(int i = 0; i <= n; i++)
{
C[i][0] = C[i][i] = 1;
for(int j = 1; j < i; j++)
C[i][j] = (C[i-1][j-1] + C[i-1][j]) % p;
}
}
LL ans = 0;
int dfs(int p,int c)
{
LL ret = 0;
if(c==0) return 1;
if(p>=str.length()) return 0;
if(str[p]=='1')
{
upd(ret,dfs(p+1, c-1));
upd(ret,C[str.length()-p-1][c]);
}
else
upd(ret,dfs(p+1,c));
return ret;
}
int main(int argc ,char const *argv[])
{
#ifdef GoodbyeMonkeyKing
freopen("Input.txt","r",stdin);freopen("Output.txt","w",stdout);
#endif
comb(1000, 1000, MOD);
vector<int > vec;
int k;
cin>>str>>k;
if(k==0) return cout<<1<<endl,0;
for (int i = 1; i <= 1000; ++i)
{
int temp = 0;
bitset<13> bs(i);
for (int i = 0; i < 13; ++i)
if(bs[i])
temp++;
down[i] = temp;
}
tms[1] = 0;
for (int i = 2; i <= 1000; ++i)
{
tms[i] = tms[down[i]]+1;
if(tms[i]==k-1)
vec.push_back(i);
}
if(k==1) vec.push_back(1),ans--;
for (int i = 0; i < vec.size(); ++i)
if(vec[i]<=str.length())
upd(ans,dfs(0, vec[i]));
cout<<ans<<endl;
return 0;
}