百度之星:寻找母串/HDU 6084 寻找母串

25 篇文章 0 订阅
7 篇文章 0 订阅

百度之星:寻找母串/HDU 6084 寻找母串

题目

题目链接

Problem Description
对于一个串S,当它同时满足如下条件时,它就是一个01偏串:
 1、只由0和1两种符组成; 
 2、在S的每一个前缀中,0的个数不超过1的个数;
 3、S中0的个数和1的个数相等。
现在给定01偏串S,请计算一下S在所有长度为n的01偏串中作为子串出现的次数的总和。 由于结果比较大,结果对1e9+7取余后输出。

Sample Input
2
2 10
4 10

Sample Output
1
3
样例解释:
在第二个样例中,长度为4的偏串共两个1010,1100。10在1010中出现了两次,在1100中出现了1次。所以答案是3。
Input
第一行给出一个整数T(1<=T<=40),表示测试数据的数目。 每一组测试包含一个整数n和字符串S,中间用空格分开。(1<=|S|<=100000,1<=n<=1000000000)
输入保证S是一个01偏串。
Output
对于每一组数据,输出一个整数占一行,表示答案。

题目大意:

对于一个串S,当它同时满足如下条件时,它就是一个01偏串:

  1. 只由0和1两种符组成;
  2. 在S的每一个前缀中,0的个数不超过1的个数;
  3. S中0的个数和1的个数相等。
    现在给定01偏串S,请计算一下S在所有长度为n的01偏串中作为子串出现的次数的总和。
    由于结果比较大,结果对 1 0 9 + 7 10^9+7 109+7取余后输出。

解析

打表?暴力?额,好像不会做。

其实01偏串实际上等价于合法括号序列,在合法括号序列中取出一个合法括号序列之后剩下的一定也是一个合法括号序列
所以我们计算 n − l e n S n-lenS nlenS的合法括号序列数,乘上 S S S n n n中的位置种类即可,计算卡特兰数时候因为模比较大,我们采用分段打表。注意n-s<0||(n-s)%2==1条件的特判。

然后一开始打 s q r t ( n ) sqrt(n) sqrt(n)的表,代码长度超限
1 0 5 10^5 105还是超。。
于是 1 0 6 10^6 106终于过了
本来要是还不过就不会了。。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const LL MOD=1000000007,blk=500000;
const LL lst[2001]={……};
int T,n,s;
char ss[1000010];
LL Fact(LL x){
    if(x<0)return 0;
    LL res=lst[x/blk];
    for(LL i=(x/blk)*blk+1;i<=x;i++)res=(res*i)%MOD;
    return res;
}
LL power(LL a,LL b){
    if(b==0)return 1;
    if(b&1)return(power(a,b-1)*a)%MOD;
    LL t=power(a,b/2);return (t*t)%MOD;
}
LL C(LL a,LL b){
    if(a<0||b<0||a<b)return 0;
    return(Fact(a)*power(Fact(a-b),MOD-2)%MOD*power(Fact(b),MOD-2))%MOD;
}
LL Calc(int x){return (C(2*x,x)-C(2*x,x-1)+MOD)%MOD;}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d %s",&n,ss);
        s=strlen(ss);
        if(n-s<0||(n-s)%2==1)puts("0");
        else printf("%d\n",Calc((n-s)/2)*(n-s+1)%MOD);
    }return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值