zoukankan      html  css  js  c++  java
  • Day12 T1 少女觉

    题目

    在幽暗的地灵殿中,居住着一位少女,名为古明地觉。
    据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心。
    掌控人心者,可控天下。
    人的记忆可以被描述为一个黑块(B)与白块(W)的序列,其中情感值被定义为序列中黑块数量与白块数量之比。
    小五口在发动读心术时,首先要解析人的记忆序列,因此,需要将序列分割为一些段,并且要求每一段记忆序列的情感值都相等。
    下面给出两个例子:
    BWWWBB -> BW + WWBB (Ratio=1:1)
    WWWBBBWWWWWWWWWB -> WWWB + BBWWWWWW + WWWB (Ratio=3:1)
    现在小五手上有一个人的记忆序列,她想要知道,如何将手中的记忆序列分成尽可能多的段呢?

    输入

    第一行包含一个正整数T,代表数据组数。
    对于每一组测试数据,第一行包含一个正整数N。
    接下来N行描述一个序列,每行包含一个正整数K和一个大写字母C,表示序列接下来有连续K个颜色为C的方块。

    输出

    对于每组测试数据输出一行一个正整数,表示最多分成的段数。

    样例

    输入 输出
    3
    3
    1 B
    3 W
    2 B
    4
    3 W
    3 B
    9 W
    1 B
    2
    2 W
    3 W
    2
    3
    5

    数据范围

    对于10%的数据,(Nleqslant15)
    对于20%的数据,(Nleqslant500)
    另有30%的数据,(K=1)
    另有30%的数据,(Kleqslant50)
    对于100%的数据,(Nleqslant10^5),序列长度不超过(10^9)
    保证对于全部测试点,输入文件行数不超过(2.5 imes10^6)

    题解

      因为每一段记忆序列的情感值都相等,设为K,那么由合比性质我们很容易知道,整个序列的情感值也为K。
      一旦情感值确定下来了,我们的分割就很方便了。很容易想到,遍历一遍序列,每当情感值为K时就分割,然后重新统计W和B的数量,当情感值为K时再分割,如此反复。
      然而,如果我们直接扫一遍整个序列,(10^9)的长度可能会超时。
      由合比性质,我们可以知道,若干分割出的小序列拼起来之后的序列的情感值也为K。那么我们就可以由当前W(B)的数量计算出要达到K我们还需要多少B(W),而再次达到K的时候,我们就可以再分割出一个小序列。
      如果当前我们所遍历到的这一段,B(W)的数量可以满足在这一段的某个位置,情感值再次达到K,那么我们就可以再当前的这一段分割出一个小序列。如果计算出当前需要的不是整数个,那么说明以当前的W(B)的数量,我们无法让情感值达到K,也就无法再分割出一个小序列。
    PS:此题解部分借鉴星星之火OIer的博客

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN=1e5+10;
    int rnd,n;
    
    ll cal(ll x,ll a,ll b){//用于计算还需要多少B(W)
        //因为x*b可能爆int,而如果先除,因为无法确定a是哪一个的约数,有可能因为下取整而使答案错误,所以要开ll
        return (x*b)%a ? -1 : x*b/a;
    }
    
    int main(){
        // freopen("silly.in","r",stdin);
        // freopen("silly.out","w",stdout);
        scanf("%d",&rnd);
        while(rnd--){
            ll times[MAXN];
            char ch[MAXN][2];
            ll sumb=0,sumw=0;
            scanf("%d",&n);
            for(register int i=1;i<=n;i++){
                scanf("%lld %s",&times[i],&ch[i]);
                if(ch[i][0]=='B') sumb+=times[i];
                if(ch[i][0]=='W') sumw+=times[i];
            }
            if(!sumb || !sumw){//如果全是B或W,则可以分成序列长(sumb+sumw)段
                printf("%d
    ",sumb+sumw);
                continue;
            }
            ll cntb=0,cntw=0;
            int ans=0;
            for(register int i=1;i<=n;i++){
                if(ch[i][0]=='B'){
                    ll p=cal(cntw,sumw,sumb);
                    if(p>cntb && p<=cntb+times[i]) ans++;
                    cntb+=times[i];
                }
                if(ch[i][0]=='W'){
                    ll p=cal(cntb,sumb,sumw);
                    if(p>cntw && p<=cntw+times[i]) ans++;
                    cntw+=times[i];
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Web后台项目学习2(代码部分)
    Web后台项目学习
    JDBC
    爬虫视频
    asyncio
    一篇做实验的随笔
    day14
    day13
    html+css 习题
    js-练习题
  • 原文地址:https://www.cnblogs.com/znk161223/p/12219181.html
Copyright © 2011-2022 走看看