codeforces 1295B Infinite Prefixes 思维

33 篇文章 0 订阅

https://vjudge.net/problem/CodeForces-1295B
在这里插入图片描述题目大意:给定一个长度为 n n n 01 01 01串,设其为 s s s,那么字符串 t = s s s s … … t=ssss…… t=ssss,设一个字符串 q q q的平衡值为 c n t 0 − c n t 1 cnt_0-cnt_1 cnt0cnt1,其中 c n t 0 cnt_0 cnt0为字符串 q q q 0 0 0的个数, c n t 1 cnt_1 cnt1为字符串 q q q 1 1 1的个数,现在给定字符串 s s s和一个值 x x x,问字符串 t t t的前缀中平衡值等于 x x x的前缀个数,如果这样的前缀有无穷多个,那么输出 − 1 -1 1
思路:设字符串 s s s的前缀 s i s_i si的平衡值为 v i v_i vi,那么字符串 t t t的前缀的平衡值为:
v 1 , v 2 , v 3 , … … , v n v_1,v_2,v_3, ……,v_n v1,v2,v3,,vn
v n + v 1 , v n + v 2 , v n + v 3 , … … , 2 ∗ v n v_n+v_1,v_n+v_2,v_n+v_3,……,2*v_n vn+v1,vn+v2,vn+v3,,2vn
2 ∗ v n + v 1 , 2 ∗ v n + v 2 , 2 ∗ v n + v 3 , … … , 3 ∗ v n 2*v_n+v_1,2*v_n+v_2,2*v_n+v3,……,3*v_n 2vn+v1,2vn+v2,2vn+v3,,3vn
不难发现,如果平衡值等于 x x x的前缀个数有无穷多个,那么必定有 v n = 0 v_n=0 vn=0,否则解一定是有限的。对于前缀 s i s_i si,如果满足 ( x − v i ) % v n = 0 (x-v_i)\%v_n=0 (xvi)%vn=0 x − v i x-v_i xvi v n v_n vn同号,那么 s i s_i si就对答案有贡献。当然还有一种特殊情况我们没有考虑到,就是前缀为空字符串的时候,当且仅当 x = 0 x=0 x=0时空字符串才对答案有贡献。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

const int maxn=1e5+5;

char s[maxn];
int v[maxn];

int main()
{
    int t,n,x;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%s",&n,&x,s+1);
        int len=strlen(s+1);
        int cnt1=0,cnt2=0;
        bool flag=0;
        for(int i=1;i<=len;i++)
        {
            if(s[i]=='1')
                ++cnt1;
            else
                ++cnt2;
            v[i]=cnt2-cnt1;
            if(v[i]==x)
                flag=1;
        }
        if(x==0)
            flag=1;
        if(v[n]==0)
        {
            if(flag)//平衡值等于x的前缀存在 则有无穷多个
                printf("-1\n");
            else //前缀不存在 那么答案自然为0
                printf("0\n");
        }
        else
        {
            int ans=0;
            if(x==0)//前缀为空字符串时仅对x=0有贡献
                ++ans;
            for(int i=1;i<=len;i++)
                if((x-v[i])%v[n]==0&&(x>=v[i]&&v[n]>0||x<=v[i]&&v[n]<0))
                    ++ans;
            printf("%d\n",ans);
        }
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值