题目链接:C. And and Pair
可以找规律,当然也可以数位dp。
只不过这个数位dp是二维的数位dp。
我们对于每一个数字:如果当前某一位二进制为1,但是n这一位不为1,那么不合法,continue。
如果当前这一位 i,j都为1,也不合法,continue。
然后我们没有处理 i == j 和 j<= i 的关系的情况,i == j 并且合法,那么都为。我们利用对称性除以二就可以避免 j>i 然后加上 1就行了。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,p=1e9+7;
int T,dp[N][2][2],n; char str[N];
inline int qmi(int a,int b=p-2){
int res=1;
while(b){if(b&1) res=res*a%p; b>>=1; a=a*a%p;}
return res;
}
int dfs(int pos,int l1,int l2){
if(!pos) return 1;
if(dp[pos][l1][l2]!=-1) return dp[pos][l1][l2];
int up1=l1?str[pos]-'0':1,up2=l2?str[pos]-'0':1,res=0;
for(int i=0;i<=up1;i++){
for(int j=0;j<=up2;j++){
if((i&&(str[pos]=='0'))||(i==1&&j==1)) continue;
res=(res+dfs(pos-1,l1&&i==up1,l2&&j==up2))%p;
}
}
dp[pos][l1][l2]=res;
return res;
}
inline int solve(){
n=strlen(str+1); reverse(str+1,str+1+n);
return dfs(n,1,1);
}
signed main(){
cin>>T; int inv=qmi(2);
while(T--){
scanf("%s",str+1); memset(dp,-1,sizeof dp);
printf("%lld\n",(solve()+1)*inv%p);
}
return 0;
}