题目链接:传送门
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
3
样例输出
-
3
描述
如果一个二进制数包含连续的两个1,我们就称这个二进制数是非法的。
小Hi想知道在所有 n 位二进制数(一共有2n个)中,非法二进制数有多少个。
例如对于 n = 3,有 011, 110, 111 三个非法二进制数。
由于结果可能很大,你只需要输出模109+7的余数。
输入
一个整数 n (1 ≤ n ≤ 100)。
输出
n 位非法二进制数的数目模109+7的余数。
解题思路:用数位dp求出合法的二进制数个数num,然后2^n-num
dp[pos][state]:state记录二进制数的前一位是否为1。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <stack>
#include <algorithm>
#include <map>
#include <bitset>
using namespace std;
typedef long long ll;
const int N = 105;
const int M = 1000009;
const int INF = 0x3fffffff;
const int mod = 1e9+7;
const double Pi = acos(-1.0);
const double sm = 1e-9;
typedef pair<int,int>PA;
int a[N],dp[N][2],re[N];
void getRe()
{
re[0] = 1;
for( int i = 1 ; i < N ; ++i ){
re[i] = re[i-1]*2%mod;
}
}
int dfs( int pos , int state , int flag , int limit )
{
if( pos == -1 ) return flag == 0;
if( dp[pos][state] != -1 && !limit ) return dp[pos][state];
int up = (limit==0)?1:a[pos];
int ans = 0;
for( int i = 0 ; i <= up ; ++i ){
if( flag || (i==1&&state) ) continue;
ans = (ans+dfs( pos-1 , i == 1 , flag||(i==1&&state) , limit&&(i==a[pos]))%mod)%mod;
}
if( !limit ) dp[pos][state] = ans;
return ans;
}
int solve( int n )
{
for( int i = 0 ; i < n ; ++i ) a[i] = 1;
return dfs( n-1 , 0 , 0 , 1 );
}
int main()
{
int n;
getRe();
memset( dp , -1 , sizeof(dp) );
while( cin >> n ){
int ans = solve(n);
ans = re[n]-ans;
if( ans < 0 ) ans += mod;
cout << ans << endl;
}
return 0;
}