題目大意:c++
給定n k 給定一個數的二進制位a[]ide
求這個數加上 另外一個二進制位<=n的數b 後spa
能獲得多少個不一樣的 二進制位有k個1 的數code
要讓數變大 考慮把0變爲1 這樣變化能保證獲得的數絕對變大blog
對於第一個0此時遇到了1 即到了10001xxxxx
由於要保證>= 1000100111
因此1必須固定不能變換
那麼 繼續看下一個0input
100010xxxx 變爲 100011xxxx
方案數是C(4,2)
1000100xxx 變爲 1000101xxx
方案數是C(3,2)
而後1000100111自己也是一種方案it
會發現其實就是在0位累加組合數event
1 0 0 0 1 0 0 1 1 1class
C(8,3)+C(7,3)+C(6,3) +C(4,2)+C(3,2) +1(自己)cli
因此10位的可能方案有 56+35+20+6+3+1=121
要讓數變小 就考慮把1變爲0
由於必須保證11位 因此默認第一位爲1
對於第二個1
11xxxxxxxxx 變爲 10xxxxxxxxx
剩下的x中須要再有4個1 因此方案數是C(9,4)
對於第三個1
110001xxxxx 變爲 110000xxxxx
方案數是C(5,3)
對於第四個1
110001001xx 變爲 110001000xx
方案數是C(2,2)
對於第五個1
1100010011x 變爲 1100010000x
方案數是C(1,1)
而後11000100110自己也是一種方案
1 1 0 0 0 1 0 0 1 1 0
C(9,4) +C(5,3) +C(2,2)+C(1,1) +1(自己)
因此11位的可能方案有 126+20+1+1+1=149
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define mem(i,j) memset(i,j,sizeof(i)) #define inc(i,j,k) for(int i=j;i<=k;i++) #define dec(i,j,k) for(int i=j;i>=k;i--) const int N=1e3+5; const int mod=1e9+7; int n,k,a[N]; char s[N]; LL C[N][N]; void init() { C[0][0]=C[1][0]=C[1][1]=1LL; inc(i,2,N-1) { C[i][0]=1LL; inc(j,1,i-1) { C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } C[i][i]=1LL; } } int main() { init(); while(~scanf("%d%d%s",&n,&k,s)) { int cnt=0; inc(i,0,n-1) { if(s[i]=='0')a[i]=0; else a[i]=1, cnt++; } if(k==0) { if(cnt==0) printf("1\n"); else printf("0\n"); continue; } if(cnt==0) { printf("%d\n",C[n][k]); continue; } LL ans=0; int U=k-1, D=n-1; inc(i,0,n-1) { if(U<0) break; if(a[i]==1) U--; else ans=(ans+C[D][U])%mod; D--; } if(cnt<=k) ans=(ans+1LL)%mod; // 自己 reverse(a,a+n); inc(i,0,n-1) { a[i]+=1; if(a[i]>1) a[i+1]++; a[i]%=2; } reverse(a,a+n+1); U=k-1, D=n-1; inc(i,1,n) { if(U==0) break; if(a[i]==1) { ans=(ans+C[D][U])%mod; U--; } D--; } cnt=0; inc(i,0,n) if(a[i]==1) cnt++; if(cnt>=k) ans=(ans+1LL)%mod; // 自己 printf("%lld\n",ans); } return 0; }