• F. Shifting String #797div3


    F. Shifting String #797div3 

    Problem - F - Codeforces

    题意是给你一个字符串和一个排列,s1s2s3s4...变成sp1,sp2,sp3...

    比如abcd 4 2 1 3=>dbac

    问你至少操作多少次可以变成原来的字符串

    这题一看就是周期问题,然后我直接上手暴力,不出意外的tle了hh

    不要那么一根筋啊,要多想想的

    仔细揣摩可以发现 如果像是ab 21的话,会一直变成ba ab...这样子循环,那这对循环与其他字母怎么循环无关,这样命名一下为一个环。然后整个序列里面可以找到若干个这样的环,不管怎么循环,它们循环自己的与其他无关。这样的话,整个序列的周期就是所有环的lcm(最小公倍数)

    注意一点:环的长度!=这个环的周期 刚开始我怎么也没想出来

    把环求出来还需要求一下这个环的周期

    周期怎么求:最长不可能超过这个环的长度,因为最坏的情况是全部循环一遍,直接上个公式吧:s[(a+k)%cnt]==s[a]如果每个字母都可以满足这个条件,说明循环一遍之后还是它,从小到大枚举满足条件的就是最小周期

    周期还有一种求法,一位大佬提醒用kmp可以把时间复杂度优化到O(n),我不会QAQ...

    (其实还有一种方法,我不会映射而已...QAQ)

    1. #pragma GCC optimize(1)
    2. #pragma GCC optimize(2)
    3. #pragma GCC optimize(3,"Ofast","inline")
    4. #define IOS ios::sync_with_stdio(false), cin.tie(0);
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. using namespace std;
    16. typedef long long ll;
    17. typedef pair<int,int> PAII;
    18. const int N=2e6+10,M=5050,INF=0x3f3f3f3f,mod=998244353;
    19. int read()
    20. {
    21. int x = 0, f = 1;
    22. char c = getchar();
    23. while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    24. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    25. return x * f;
    26. }
    27. int p[N];
    28. bool st[N];
    29. char ch[N],s[N];
    30. int main(){
    31. IOS;
    32. int T;
    33. //T=1;
    34. cin>>T;
    35. while(T--)
    36. {
    37. int n;
    38. cin>>n;
    39. cin>>ch+1;
    40. for(int i=1;i<=n;i++)
    41. {
    42. cin>>p[i];
    43. st[i]=false;
    44. }
    45. ll res=1;
    46. for(int i=1;i<=n;i++)
    47. {
    48. if(!st[i])
    49. {
    50. int cnt=0;
    51. for(int j=i;!st[j];st[j]=true,j=p[j]) s[cnt++]=ch[j];//找到环**
    52. ll t;
    53. for(int k=1;k<=cnt;k++)//找周期 周期最多是长度
    54. {
    55. if(cnt%k==0)
    56. {
    57. int f=1;
    58. for(int z=0;z
    59. {
    60. if(s[(z+k)%cnt]!=s[z])
    61. {
    62. f=0;
    63. break;
    64. }
    65. }
    66. if(f)
    67. {
    68. t=k;
    69. break;
    70. }
    71. }
    72. }
    73. res=res/__gcd(t,res)*t;
    74. }
    75. }
    76. cout<"\n";
    77. }
    78. return 0;
    79. }
    80. /*
    81. */

    多积累题目经验吧.

    ******************************************************

    Problem - C - Codeforces

    题意是给你一个排列a,一个排列b,给一个序列c,如果c等于0,从ai或者bi任意选一个数 保证ci一定为ai bi中的任意一个,问有多少种这样的方案,要保证c是个排列

    这个题也是和环有关的,予以并查集进行实现

    因为你会发现 如果有一个值你知道了,接下来的一连串的数你可能都确定了

    所以这就是个突破口

    可以把ab序列划分成若干个环,环的性质是只要你确定了其中的任何一个数,那整个环的其他数字你全都知道了。所以在找到环的时候,你还需要判断一下这个环里面有没有确定的数字,如果有,那很好,这个环的贡献是1,(其实由于乘法原理,这个1是乘的1可以不用管),如果没有,那这个环的贡献就是2,很好证,其实就是一个位置有两种选择,每选一种其他数字都确定进而全部的环的选择也就是贡献为2。但是这里注意一下,如果某个环的长度是1,那贡献也是1

    1. #pragma GCC optimize(1)
    2. #pragma GCC optimize(2)
    3. #pragma GCC optimize(3,"Ofast","inline")
    4. #define IOS ios::sync_with_stdio(false), cin.tie(0);
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. using namespace std;
    16. typedef long long ll;
    17. typedef pair<int,int> PAII;
    18. const int N=2e6+10,M=5050,INF=0x3f3f3f3f,mod=1e9+7;
    19. int a[N],b[N],c[N],p[N];
    20. bool st[N],s[N];
    21. int main(){
    22. //IOS;
    23. int T;
    24. //T=1;
    25. cin>>T;
    26. while(T--)
    27. {
    28. int n;
    29. cin>>n;
    30. for(int i=1;i<=n;i++) st[i]=false,s[i]=false;
    31. for(int i=1;i<=n;i++) cin>>a[i];
    32. for(int i=1;i<=n;i++) cin>>b[i];
    33. for(int i=1;i<=n;i++)
    34. {
    35. cin>>c[i];
    36. if(c[i])
    37. {
    38. st[a[i]]=true;
    39. st[b[i]]=true;
    40. }
    41. }
    42. for(int i=1;i<=n;i++) p[a[i]]=b[i];
    43. ll res=1;
    44. for(int i=1;i<=n;i++)
    45. {
    46. if(!s[i])
    47. {
    48. int f=0,cnt=0;
    49. for(int j=i;!s[j];j=p[j])
    50. {
    51. s[j]=true;
    52. cnt++;
    53. f=f|st[j];
    54. }
    55. if(cnt!=1&&!f) res=res*2%mod;
    56. }
    57. }
    58. cout<"\n";
    59. }
    60. return 0;
    61. }
    62. /*
    63. */

  • 相关阅读:
    【生成模型】Diffusion Models:概率扩散模型
    【SA8295P 源码分析】103 - QNX DDR RAM 内存布局分析
    Linux的shell脚本在线转换为Windows的bat脚本
    项目实战:组件扫描(2)-获取bean组件存放到IOC容器
    windows 11部署wsl环境
    Servlet简单项目操作
    清华学姐三年的测试成长经历,到最后的喜提高薪offer
    用户登录问题
    hyperscan技术
    堆外内存泄露排查思路及案例分享
  • 原文地址:https://blog.csdn.net/m0_63305704/article/details/126438209