hihoCoder1318—非法二进制数(数位dp)

来源:互联网 发布:广州java 外包公司 编辑:程序博客网 时间:2024/05/20 03:43

题目链接:传送门

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

如果一个二进制数包含连续的两个1,我们就称这个二进制数是非法的。

小Hi想知道在所有 n 位二进制数(一共有2n个)中,非法二进制数有多少个。

例如对于 n = 3,有 011, 110, 111 三个非法二进制数。

由于结果可能很大,你只需要输出模109+7的余数。

输入

一个整数 n (1 ≤ n ≤ 100)。

输出

n 位非法二进制数的数目模109+7的余数。

样例输入
3
样例输出
3

解题思路:用数位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;}


原创粉丝点击