时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
3
样例输出
-
3
描述
如果一个二进制数包含连续的两个1,我们就称这个二进制数是非法的。
小Hi想知道在所有 n 位二进制数(一共有2n个)中,非法二进制数有多少个。
例如对于 n = 3,有 011, 110, 111 三个非法二进制数。
由于结果可能很大,你只需要输出模109+7的余数。
输入
一个整数 n (1 ≤ n ≤ 100)。
输出
n 位非法二进制数的数目模109+7的余数。
思路:一道dp的题目,到当前位置增加的非法二进制数是由其低位所构成的.以n为例,其由三种情况构成:
1.当最高位为0,则非法二进制数是和n-1时候的非法二进制数相等的.
2.当最高位为1,次高位也为1,那么剩余(n-2)位就有2^(n-2)个非法二进制数
3.当最高位为1,次高位为0,其非法二进制数是和(n-2)相等的
因此其dp方程为dp[n] = dp[n-2] + dp[n-1] + 2^(n-2);
需要注意的是在求2^(n-2)时不能直接移位求,因为n很大会溢出,需要一位一位的移动,并且每次都要除余(10^9 + 7);
代码如下:
/*************************************************************************
> File Name: illegal.cpp
> Author: Maoting Ren
> Mail: mren@g.clemson.edu
> Created Time: Sun 05 Jun 2016 12:13:51 AM EDT
************************************************************************/
#include<iostream>
#include<vector>
#include<math.h>
#include<stdlib.h>
using namespace std;
int getNum(int x)
{
int result = 1;
for(int i = 1; i <= x; i++)
result = (result<<1)%((int)(pow(10, 9)+7));
return result;
}
int main()
{
int n;
cin >> n;
if(n <= 2)
{
if(n == 1) cout << "0" << endl;
else cout << "1" << endl;
exit(0);
}
vector<long> dp(n+1, 0);
dp[2] = 1, dp[3] = 3;
for(int i = 4; i <= n; i++)
dp[i] = (dp[i-1] + dp[i-2] + getNum(i-2))%((int)(pow(10, 9)+7));
cout << dp[n] << endl;
return 0;
}