链接:
https://www.nowcoder.com/acm/contest/107/E
来源:牛客网
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
众所周知,Xieldy最常用的口令是******。
为了改变这一现状,他random了一个01串,并从中截取了一段作为自己的口令。
他选择的口令满足以下条件:
1. 口令串表示的二进制数在十进制下可以被表示为3k(k>=0)。
2. 口令串可以有前导零。
现已经random出了01串,他想知道有多少种口令方案可以选择(不同的子段即为不同)。
为了改变这一现状,他random了一个01串,并从中截取了一段作为自己的口令。
他选择的口令满足以下条件:
1. 口令串表示的二进制数在十进制下可以被表示为3k(k>=0)。
2. 口令串可以有前导零。
现已经random出了01串,他想知道有多少种口令方案可以选择(不同的子段即为不同)。
输入描述:
若干组数据,每组数据仅一行01串s,表示random出来的的串,|s|<=1e6。
输出描述:
输出口令的方案数。
思路:首先一个二进制数的后面加一个0相当于该数乘2,加1相当于该数乘2+1.
dp[i][j]表示的是以i结尾的二进制数求余3余j的个数。
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+300; char str[maxn]; long long dp[maxn][3]; int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); while(~scanf("%s",str)){ memset(dp,0,sizeof(dp)); int len = strlen(str); if(len == 0) {printf("0\n");continue;} dp[0][str[0]-'0']=1;//自己本身 long long res = dp[0][0]; for(int i=1;i<len;i++){ int f = str[i]-'0'; dp[i][f]++;//自己本身 if(f==0){ dp[i][0]+=dp[i-1][0]; dp[i][2]+=dp[i-1][1]; dp[i][1]+=dp[i-1][2]; } else{ dp[i][1]+=dp[i-1][0]; dp[i][0]+=dp[i-1][1]; dp[i][2]+=dp[i-1][2]; } res += dp[i][0]; } printf("%lld\n",res); } return 0; }