Lighting (上下界數位dfs)
阿新 • • 發佈:2018-12-22
題意:
給一個n位2進位制數a,求有多少個n位2進位制b使a+b的二進位制表示有恰好k個1
解析:
因為不考慮字首0,所以b的取值範圍為0~11…11,我們就得出了a+b的範圍,跑一個帶上下界的dfs即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
char up[1009],down[1009];
int len,maxpos;
LL C[1009][1009];
void init(int n,int k){
//////////////C
for(int i=0;i<= 1005;i++)C[i][0]=1;
for(int i=1;i<=1005;i++){
for(int j=1;j<=i;j++){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
//////////////up
len=strlen(down+1);
reverse(down+1,down+1+len);
strcpy(up+1,down+1);
up[len+1]='1';up[len+2]='\0';
//////////////maxpos
for(int i=1;;i++) {
if(up[i]=='1'){
for(int j=1;j<i;j++)up[j]='1';
up[i]='0';
break;
}
}
//cout<<up+1<<endl;
maxpos=len;
if(up[len+1]=='1')maxpos++;
}
LL dfs(int pos,int res,bool fup,bool fdown){
//當前位,剩餘1,上下界滿足與否
if(pos==0)return res== 0;
if(pos<res)return 0;
if(fup&&fdown)return C[pos][res];
//剪枝:接下來全填1 只需考量上界
if(pos==res){
if(fup)return 1;
else{
if(!(up[pos]=='1'))return 0;
else return dfs(pos-1,res-1,fup,fdown);
}
}
//剪枝:接下來全填0 只需考量下界
if(res==0){
if(fdown)return 1;
else{
if(down[pos]=='1')return 0;
else return dfs(pos-1,res,fup,fdown);
}
}
//分幾種情況
LL ans=0;
if(fup&&!fdown){
if(down[pos]=='1'){
ans+=dfs(pos-1,res-1,fup,fdown);
}
else{
ans+=dfs(pos-1,res-1,fup,1);
ans+=dfs(pos-1,res,fup,fdown);
}
}
else if(!fup&&fdown){
if(!(up[pos]=='1')){
ans+=dfs(pos-1,res,fup,fdown);
}
else{
ans+=dfs(pos-1,res,1,fdown);
ans+=dfs(pos-1,res-1,fup,fdown);
}
}
else{
if((up[pos]=='1')&&(down[pos]=='1'))ans+=dfs(pos-1,res-1,fup,fdown);//1 1
else if((up[pos]=='1')&&!(down[pos]=='1'))//1 0
ans+=dfs(pos-1,res-1,fup,1),
ans+=dfs(pos-1,res,1,fdown);
else if(!(up[pos]=='1')&&!(down[pos]=='1'))//0 0
ans+=dfs(pos-1,res,fup,fdown);
}
return ans%mod;
}
int main(){
int n,k;
cin>>n>>k>>down+1;
init(n,k);
LL ans=0;
ans=dfs(maxpos,k,0,0);
printf("%lld\n",ans);
}