ABC347

B Substring

题目描述

给你一个由小写英文字母组成的字符串 S, S 有多少个不同的非空子串?

子串是连续的子序列。例如,xxx是yxxxy的子串,但不是xxyxx的子串。

数据范围:S 是长度在 1 和 100 之间(含)的字符串,由小写英文字母组成。
题解

我认为这道题放在普及组的话,非常适合放在第一题和第二题之间,当我们看到数据范围是100的话,这个最大可承受的时间复杂度是\(O(n^4)\),所以我们可以枚举。这里要求的是所以不同的非空子串的长度,所以我们需要在每个长度上都找出是否有相同的子串,比如说yay,在长度为1的时候,就是相同的非空子串

所以第一个维度我们应该先枚举长度len,第二个维度枚举起点i,那么终点我们就知道了,是j=i+len,对于每一个\((i,j)\)之间的子串,我们来比较长度为len的,起点k在\([1-i-1]\)的所有子串,是否和\([i,len]\)的子串相同,所以我们枚举len,枚举起点i,枚举子集的起点k,比较字符串是否相等,时间复杂度是\(o(n^4)\),代码如下:

点击查看代码
#include <bits/stdc++.h>

using namespace std;

const int maxn=105;
char s[maxn];

int ans;
int main(){
    scanf("%s",s+1);
    int n=strlen(s+1);
    for(int len=1;len<=n;len++){
        for(int i=1;i<=n;i++){
            if(i+len-1>n) break;
            int cnt=0;
            for(int j=1;j<i;j++){
                int k=0;
                while(s[i+k]==s[j+k]&&k<len) k++;
                if(k==len) {
                    cnt=1;
                    break;
                }
            }
            if(cnt==0) {
                //cout<<i<<endl;
                ans+=1;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

C Ideal Holidays

题目大意:

   一个星期是由a天和b天组成,[1—a]天是假期,[a+1,a+b]是工作日,现在并不知道是星期几,那么接下来的n个计划,分别是d[i]天,表示在星期几的d[i]天之后,问这些计划能否在假期进行?

题解

这个题,我是在考场时做不出来的,只会枚举这一个操作,但是\(1\leq a,b \leq 10^9\),如果枚举a+b的话,一定会TLE。
正解应该怎么做?
我们假设当前是星期一,那么我们用所有的d[i]%(a+b)得到一个数值b[i],那么我们的b[i]就是以星期一为基础的星期x。
如果星期x,所有的值都延后x天,所以我们想延后x天之后,这些数值能否在假期,也就是[1,a]范围内
如果\(b[n]-b[1] <a\),那么所有的计划就都在假期内
如果\(b[i]-b[i-1]>b\),那么所有的计划就都在假期内
这两个条件随便满足一个就行,第一个条件可以理解,为什么第二个条件也成立呢?
所有的值都在[0,a+b-1]范围内,如果相减的值大于b
一种情况是两个值都在假期,因为他们跨过了假期
一种情况是

算了,这个题我还没有想明白,之后再说吧

D Popcount and XOR

题目大意

非负整数a,b,c,已知a里面二进制1的个数是x,b里面二进制1的个数是y,\(a \oplus b=c\),也就是说a异或b等于c,现在给定x,y和c,请找出一对(a,b)满足条件?

题解

再次做这个题,看错题了,可悲啊
如果我们已经计算出来了c里面有多少个1,那么我们很容易计算出a和b里有多少个相同的1,(x+y)/2就是相同个1的个数,那么a和b里面不同的1的个数就知道了,假设我们求出了不同的1的个数分别是tx和ty,这些位置肯定是10和01的位置,那么我们枚举C,如果C的位置为1,那么我们先让a左移,如果a的10的位置已经用光,则让b左移,如果c的位置为0,那么说明a和b都是1,都左移,这样a和b就都找到了

E Set Add Query

题目大意

给定n个数字,范围在[1,n],一次将a[i]加入到集合中,如果a[i]已经存在集合中的话,那么将a[i]从集合中去掉,每次都把集合里的元素加上集合个数,最后问数组是多少?
比如
1 3 3 2
先是 1
然后是3 0 2
然后是4 0 2
然后是6 2 2

题解

这个是考差分和前缀和的题,cf[i]表示第i个位置被加了多少,最后我们从右向左记录前缀和,那么前缀和其实就是最后的数组
例如 1 2 3 cf 1 2 3 sum 6 5 3 第一个位置被加了6,第二个位置的数字被加了5,低三个位置上的数字被加了3
这么处理麻烦的是有的数字重复出现了,我们可以通过pre[i]记录上次出现的位置,如果重复出现了,说明这个数字已经不在这一段区间了,那我们找到上一次出现的位置,我们对这个数字而言,只在这里记录就行,而且他的记录终点是第二次出现的位置,所以我们需要进行区间减法,而对于那么没有重复记录的位置,他的终点就是结尾,所以我们需要加上sum数组

posted @ 2024-04-27 16:27  xinyimama  阅读(36)  评论(0编辑  收藏  举报