小 X 同学有很强的计算能力,现在他正在玩一个游戏。
现在有一个正整数 x,每次操作他会将当前的数变为这个数写成二进制后 1 的个数
小 X 不断的进行操作,直到这个数变成 1 为止
由于小 X 的计算能力很强,他现在给出一 n
他想知道有多少不超过 n 的正整数会在 k 次操作后变成 1
由于答案可能很大,请对 1000000007 取模
データ範囲のため\(2 ^ {1000年} \) 、動作するようにのみ1 1000の最大
こうして直接暴力工程1から1000のすべての数字は操作の回数が回数、1となる\(K-1 \)が表さデジタル処理スタックオペランドに追加する\(Iは\)
次のタスクは、1〜nからに含ま進数を見つけることです\(私は\)\(1 \を)
本方法は、番号のため、非常に単純な数学的組合せであるビット= 1の場合、
だから、答えはに貢献することです
\ [\巨大C_ {POS-1} ^ {I-CNT} \]
前記\(POSが\)いくつかの最初表す\(1 \)は、\ (CNTは、\)の前に数字の1を表します
その後、我々は喜んで答えを計算することができます
それはピット\(K = 1,0 \)特殊な文を支払うための時間
#include<bits/stdc++.h>
#define mod 1000000007
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
int k;
int num[1005],change;//num是把这个数字变为1的操作次数
vector<int> v;
char c[1005];
ll ans=0;
int one_num(int x)
{
int res=0;
while(x) {res++;x-=lowbit(x);}
return res;
}
ll fac[1005],invfac[1005];
ll qpow(ll n,ll k)
{
ll res=1;
while(k)
{
if(k&1) res=(res*n)%mod;
n=(n*n)%mod;
k>>=1;
}
return res;
}
void init()
{
fac[0]=1;
for(register int i=1;i<=1002;++i) fac[i]=(1LL*fac[i-1]*i)%mod;
}
ll inv(ll x){return qpow(x,mod-2);}
ll C(int n,int m){if(m>n||m<0) return 0;return ((1LL*fac[n]*inv(fac[m])%mod)*inv(fac[n-m]))%mod;}
int pos[1005],top=0;
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
init();
scanf("%s",c+1);
scanf("%d",&k);
if(k==0) {puts("1");return 0;}
int len=strlen(c+1);
num[1]=0;
for(register int i=2;i<=len;++i)
{
int j=i;
while(true)
{
change=one_num(j);
num[i]++;
if(change==1) break;
j=change;
}
}
// for(register int i=1;i<=len;++i) cout<<i<<" need: "<<num[i]<<endl;
for(register int i=1;i<=len;++i) if(num[i]==k-1) v.push_back(i);
//下面是计算 1~n 中有多少个数二进制中含 i 个 1
// cout<<"size:"<<v.size()<<endl;
for(register int i=len;i>=1;--i)
if(c[i]=='1') pos[++top]=len-i+1;
while(!v.empty())//循环每个i
{
ll i=v.back();
ll topp=top;
while(topp)
{
ans=(ans+C(pos[topp]-1,i-(top-topp)))%mod;
// cout<<"C "<<pos[topp]-1<<" "<<i-(top-topp)<<" "<<C(pos[topp]-1,i-(top-topp))<<endl;
topp--;
}
int cnt=0;
for(register int i=1;i<=len;++i) if(c[i]=='1') cnt++;
if(cnt==i) ans=(ans+1)%mod;
v.pop_back();
}
printf("%lld\n",ans-(k==1));
return 0;
}