1. 程式人生 > >Lighting (上下界數位dfs)

Lighting (上下界數位dfs)

題意:

給一個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); }