ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF(6.7-6.8)(从IOI到ACM)

2022-06-08 12:33:24  阅读:179  来源: 互联网

标签:return int CF ACM 6.7 read ch2 字符串 include


G

  简单叙述一下吧:类似 散步 那道题,只不过要用线段树维护不能上暴力。简单说一下线段树的思想,维护区间速度的最值,因为在左边的速度最大——维护一个不上升的序列;

  Sakura_Lu现在的马蜂还行,去看他的应该能看懂。link

 

F(Shifting String) 

    *Polycarp 找到了字符串 s 和排列 p。结果证明它们的长度相同并且等于 n。

    *n 个元素的排列 — 是一个长度为 n 的数组,其中从 1 到 n 的每个整数恰好出现一次。例如,[1,2,3] 和 [4,3,5,1,2] 是排列,但是 [1,2,4], [4,3,2,1,2] 和 [0,1 ,2] 不是。

    *在一次操作中,他可以将 s 与 p 相乘,因此他将 s 替换为字符串 new,其中对于从 1 到 n 的任何 i,newi=s*pi

    *例如,当 s=wmbe 和 p=[3,1,4,2] 时,操作后字符串会变成   s=s3s1s4s2=bwem。

    *Polycarp 想知道在经过多少次操作后,该字符串将首次等于其初始值。

输入样例:

3
5
ababa
3 4 5 2 1
5
ababa
2 1 4 5 3
10
codeforces
8 6 1 7 5 2 9 3 10 4

 输出样例:

1
6
12

    大体思路:不难想到给这些字母建边(有枪战Maf)的感觉,这些字母最终就会构成一个个的环,我们将这些环找出来,发现最终的答案就是这些环(字符串)的最小循环节长度的最小公倍数。

    所以代码分为两部分:1)找环DFS、2)求最小循环节长度KMP(蓝书有讲P74)

Code moo~~

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#define Bessie moo~~
#define int long long
using namespace std;
int read(){
    int A=0,fl=1;
    char C=getchar();
    while(C<'0'||C>'9')fl= C=='-' ? -1 : 1, C=getchar();
    while(C>='0'&&C<='9')A=(A<<3)+(A<<1)+(C^48),C=getchar();
    return A*fl;
}
int T,n,ans,tot;
int a[305],vis[305];
char ch[305],ch2[305];
void dfs(int x){
    vis[x]=1;
    ch2[tot++]=ch[x];
    if(!vis[a[x]])dfs(a[x]);
}
int nxt[305];
void getnxt(int l){
    memset(nxt,0,sizeof(nxt));
    for(int i=2,j=0;ch2[i];i++){
        while(j>0&&ch2[i]!=ch2[j+1])j=nxt[j];
        if(ch2[i]==ch2[j+1])j++;
        nxt[i]=j;
    }
}
int gcd(int x,int y){
    if(y==0)return x;
    return gcd(y,x%y);
}
int lcm(int x,int y){
    return x*y/gcd(x,y);
}
signed main(){
    T=read();
    while(T--){
        n=read();
        memset(vis,0,sizeof(vis));
        ans=1;
        for(int i=0;i<n;i++){
            cin>>ch[i];
        }
        for(int i=0;i<n;i++){
            a[i]=read();
            a[i]--;
        }
        for(int i=0;i<n;i++){
            if(!vis[i]){
                tot=1;
                dfs(i);
                // printf("%s",ch2);
                // for(int j=0;j<tot;j++)printf("%c",ch2[j]);
                getnxt(tot);
                // printf("%s",ch2);
                tot--;
                if(tot%(tot-nxt[tot])!=0){
                    // printf(" %lld\n",tot);
                    ans=lcm(ans,tot);
                }
                else {
                    // printf(" %lld\n",(tot-nxt[tot]));
                    ans=lcm(ans,tot-nxt[tot]);
                }
            }
        }
        printf("%lld\n",ans);
        // printf("\n\n");
    }
    return 0;
}

 

 

 

  后记:第一次在机房通宵,越打越兴奋,比赛结束后感觉根本不困,并且学到了线段树更灵活的用法,以及KMP求循环元的方法。

  ······吐槽一句:机房的蚊子把我的胳膊咬了5个指甲盖大小的包······

标签:return,int,CF,ACM,6.7,read,ch2,字符串,include
来源: https://www.cnblogs.com/Creator-157/p/16355199.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有