题目描述:
思路:
相比于非法二进制数,合法二进制数有规律可循,所以可以用总数减去合法二进制数的数量来求非法二进制数的数量。合法二进制数可以分为末位是1和末位是0两种情况。对于一个i位的二进制数,当末位是1时,那么前i-1位的末位必定是0(否则就不是合法数了),所以dp[i][1]=dp[i-1][0],这里dp数组的第一个下标表示二进制数的位数,第二个下标表示最低位是1还是0);当末位是0时,前i-1位末位可以是1也可以是0,所以dp[i][0]=dp[i-1][0]+dp[i-1][1];这样就得到了两个递推公式。
#include <iostream>
using namespace std;
int main()
{
long long int mod=1e9+7;
int maxn=100;
long long int dp[maxn][2];
long long int a[maxn];
int n;
cin>>n;
a[1]=2;
for(int i=2;i<=n;i++)
{
a[i]=(a[i-1]*2)%mod;
}
dp[1][1]=1;
dp[1][0]=1;
for(int i=2;i<=n;i++)
{
dp[i][1]=dp[i-1][0]%mod;
dp[i][0]=(dp[i-1][0]+dp[i-1][1])%mod;
}
long long int res=(a[n]-((dp[n][0]+dp[n][1]))%mod+mod)%mod;
cout<<res<<endl;
}
之所以使用数组a而不直接用2^n,是为了取模防止溢出;下面对dp[i][0]和dp[i][1]以及dp[i][0]+dp[i][1]取模也是同样的道理;由于a[n]-(dp[i][0]+dp[i][1])可能是个负数,所以这里加个mod再取模。