题目
Description
在一个无穷的满二叉树中,有以下几个特点:
(1) 每个节点都有两个儿子——左儿子和右儿子;
(2) 如果一个节点的编号为X,则它的左儿子编号为2X,右儿子为2X+1;
(3) 根节点编号为1。
现在从根结点开始走,每一步有三种选择:走到左儿子、走到右儿子和停在原地。
用字母“L”表示走到左儿子,“R”表示走到右儿子,“P”表示停在原地,用这三个字母组成的字符串表示一个明确的行走路线。
一个明确的行走路线的价值为最终到达节点的编号,例如LR的价值为5,而RPP的价值为3。
我们用字符“L”、“R”、“P”和“*”组成的字符串表示一组行走路线,其中“*”可以是“L”、“R”、“P”中的任意一种,所有跟这个行走路线匹配的字符串都认为是可行的。
例如L*R包含LLR、LRR和LPR。而**包含LL、LR、LP、RL、RR、RP、PL、PR和PP这9种路线。
一组行走路线的价值等于所有匹配该模式的路线的价值之和。请你编程计算给定路线的价值。
(1) 每个节点都有两个儿子——左儿子和右儿子;
(2) 如果一个节点的编号为X,则它的左儿子编号为2X,右儿子为2X+1;
(3) 根节点编号为1。
现在从根结点开始走,每一步有三种选择:走到左儿子、走到右儿子和停在原地。
用字母“L”表示走到左儿子,“R”表示走到右儿子,“P”表示停在原地,用这三个字母组成的字符串表示一个明确的行走路线。
一个明确的行走路线的价值为最终到达节点的编号,例如LR的价值为5,而RPP的价值为3。
我们用字符“L”、“R”、“P”和“*”组成的字符串表示一组行走路线,其中“*”可以是“L”、“R”、“P”中的任意一种,所有跟这个行走路线匹配的字符串都认为是可行的。
例如L*R包含LLR、LRR和LPR。而**包含LL、LR、LP、RL、RR、RP、PL、PR和PP这9种路线。
一组行走路线的价值等于所有匹配该模式的路线的价值之和。请你编程计算给定路线的价值。
Input
输入一个字符串表示一组行走路线,里面只含有“L”、“R”、“P”和“*”四种字符,长度不会超过10000。
Output
输出该路线的价值。
Sample Input
输入1: P*P 输入2: L*R 输入3: ** 输入4: LLLLLRRRRRLLLLLRRRRRLLLLLRRRRRLLLLL
Sample Output
输出1: 6 输出2: 25 输出3: 33 输出4: 35400942560
Data Constraint
Hint
【数据范围】
30%的数据满足路线中不含“*”;
50%的数据满足最多只有3个“*”。
30%的数据满足路线中不含“*”;
50%的数据满足最多只有3个“*”。
Source / Author: COCI2008
分析
-
假设经过k个*号,构造出了3^k个不同的数。
下一位是L:每个数同时*2,即总和*2
下一位是R:每个数同时*2+1,即总和*2+1*数的个数(3^k)
下一位是*:从3^k个数变成3^(k+1)个数
其中3^k个数没有变化,总和*1
另外3^k个数加上了一个L,总和*2
还有3^k个数加上了一个R,每个数*2+1,即总和*2+1*数的个数(3^k)
综上,总和*5+3^k。
加个押位高精度就没了。
代码
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int N=1e4+10,mo=1e8; 6 char s[N]; 7 int f[N],p[N]; 8 long long ans=0; 9 void mul(int x) 10 { 11 for (int i=f[0];i>=1;i--) f[i]*=x,f[i+1]+=f[i]/mo,f[i]%=mo; 12 if (f[f[0]+1]) f[0]++; 13 } 14 void tmp() 15 { 16 for (int i=p[0];i>=1;i--) p[i]*=3,p[i+1]+=p[i]/mo,p[i]%=mo; 17 if (p[p[0]+1]) p[0]++; 18 } 19 void add() 20 { 21 for (int i=1;i<=max(p[0],f[0]);i++) f[i]+=p[i],f[i+1]+=f[i]/mo,f[i]%=mo; 22 if (f[f[0]+1]) f[0]++; 23 } 24 int main () 25 { 26 int len; 27 cin>>s+1; 28 len=strlen(s+1); 29 p[0]=p[1]=f[0]=f[1]=1; 30 for (int i=1;i<=len;i++) 31 { 32 if (s[i]=='L') mul(2); 33 else if (s[i]=='R') mul(2),add(); 34 else if (s[i]=='*') mul(5),add(),tmp(); 35 } 36 cout<<f[f[0]]; 37 for (int i=f[0]-1;i>=1;i--) printf("%08d",f[i]); 38 }