CTX学长的01串

题目链接:点击打开链接

CTX学长的01串

时间限制:1 Sec内存限制:128 MiBspecial judge:No
提交:35答案正确:11

题目描述

想AK,必须过了我这一关(偷笑)。

给你一个01字符串只包括字符0和1(例如:0101010101010011010)

现在CTX学长想要考考你们,这个01串中有多少的子序列。

子序列的定义是这样的,可以在01串中找一些字符(不能改变字符的顺序)组成一个新的串,

例如01,你可以找到的子序列是"0","1","01".

例如0110,你可以找到的子序列是"0","1","01","11","10","00","011","110","010","0110".

输入

输入一个T,有T组数据。(0<T<=100)

接来下有T行,每行输入一个01串,0<长度<=100000。

输出

输出01串中有多少个不同的子序列。答案太大,输出对1000000007取余之后的结果

样例输入

复制
4
10
101
1100
00000

样例输出

复制
3
6
8
5

提示

第一个样例所包含的子序列为“0”,“1”,“10”。一共有3个子序列

第二个样例所包含的子序列为“0”,“1”,“01”,“10”,“11”,“101”。一共有6个子序列

第三个样例所包含的子序列为“0”,“1”,“00”,“10”,“11”,“100”,“110”,“1100”。一共有8个子序列

第四个样例所包含的子序列为“0”,“00”,“000”,“0000”,“00000”。一共有5个子序列.

这道题求的就是一个串中随便拿出来几个数有几种组合方式

我们可以把这个串换成一棵二叉树,根结点为空,当有一个字符出现就向下发展,0在左边,1在右边,只要能添的地方都写下新加的字符

以1100为例会形成一棵二叉树,每个结点(除了根结点)都是一种情况。


这棵树一共也就这四种结点,这四种结点都不考虑结点是什么东西,只看儿子。a:左儿子为0,右儿子为1:b:右儿子为1,左儿子为空:c:左儿子为0,右儿子为空:d:左儿子为空,右儿子为空。

当增加一个0时,b变成了a,c不变,d变成了c。至于d的话,其实d就是没有儿子的结点,那么那些有儿子的结点他们下边再加一个儿子只是让结点下移一位,还是单独一个没有儿子的结点,仍然在原来的d里边,只有那些空结点加了新结点的才会增加d,那么也就只有b会给d增加数值。最后发现b的这种结点没有了。

这道题就是通过每次加一个字符不停的变换这棵树,不停地计算这四种结点的个数,最后加起来就是这棵树的结点个数也就是最后结果。

这道题应该是一个动态规划的题目,但是我不会...

#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
char s[110000];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        int k=strlen(s);
        long long a=0,b=0,c=0,d=1;
        long long sum=0;
       for(int i=0;i<k;i++)
       {
           if(s[i]=='0')
           {
               a+=b;
               c+=d;
               d+=b;
               b=0;
           }
           else if(s[i]=='1')
           {
               a+=c;
               b+=d;
               d+=c;
               c=0;
           }
           a%=mod;
           b%=mod;
           c%=mod;
           d%=mod;
       }
       sum=(a+b+c+d-1)%mod;
       printf("%lld\n",sum);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值