zoukankan      html  css  js  c++  java
  • 【xsy1018】 小A的字母游戏 扩展CRT

    题目大意:有$n$个无限长的循环字符串,所谓循环字符串,就是由某一个子串重复叠加而成。现在想知道最早在哪一位,这n个字符串的那一位的字母相同。

    数据范围:$n≤30000$,答案$<2^{63}$。

    不难发现,此题你只要对每个字母求一个最早都出现的位置,然后取一个$min$就可以了。

    对于每个字母取一个最早大家都出现过的位置,这个显然用扩展中国剩余定理去求就可以了。

    注意此题中串长的lcm可能会爆long long 要用__int128

     1 #include<bits/stdc++.h>
     2 #define MM 30005
     3 #define L __int128
     4 using namespace std;
     5 
     6 int id[MM][52]={0},len[MM]={0};
     7 int n; 
     8 int vis[128]={0};
     9 
    10 void exgcd(L a,L b,L &x,L &y){
    11     if(b==0){x=1; y=0; return;}
    12     exgcd(b,a%b,y,x);
    13     y-=a/b*x;    
    14 }
    15 L inv(L x,L MOD){
    16     L a=0,b=0;
    17     exgcd(x,MOD,a,b);
    18     return a;
    19 }
    20 L __lcm(L m1,L m2){return m1*m2/__gcd(m1,m2);}
    21 void excrt(L &c1,L &m1,L c2,L m2){
    22     L gcd=__gcd(m1,m2),lcm=__lcm(m1,m2);
    23     if((c2-c1)%gcd) {m1=0; return;}
    24     L x=(inv(m1/gcd,m2/gcd)*((c2-c1)/gcd)%lcm*m1%lcm+c1+lcm)%lcm;
    25     c1=x; m1=lcm;
    26 }
    27 
    28 int main(){ 
    29     scanf("%d",&n);
    30     for(int x=1;x<=n;x++){
    31         memset(vis,0,sizeof(vis));
    32         char c[60]; scanf("%s",c+1);
    33         len[x]=strlen(c+1);
    34         for(int i=1;i<=len[x];i++) vis[c[i]]=i;
    35         
    36         for(int i='A';i<='Z';i++) id[x][i-'A']=vis[i];
    37         for(int i='a';i<='z';i++) id[x][i-'a'+26]=vis[i];
    38     }
    39     L ans=1e18;// ans=ans*ans; 
    40     L INF=ans;
    41     for(int x=0;x<52;x++){ 
    42         int ok=1;
    43         for(int i=1;i<=n;i++) if(id[i][x]==0) {ok=0; break;}
    44         if(ok==0) continue;
    45         L c=id[1][x],m=len[1];
    46         for(int i=2;i<=n;i++){
    47             L C=id[i][x],M=len[i];
    48             excrt(c,m,C,M);
    49             if(m==0) break; 
    50         }
    51         if(m==0) continue;
    52         if(c==0) c=m;
    53         ans=min(ans,c);
    54     }
    55     if(ans==INF) cout<<-1<<endl;
    56     else{
    57         long long out=ans;
    58         cout<<out<<endl;
    59     }
    60 }
  • 相关阅读:
    Docker部署
    编写一个脚本用户进入容器
    Shell脚本写的《俄罗斯方块》
    Linux磁盘分区(9)
    Linux任务调度(8)
    Linux权限管理(7)
    Linux组管理(6)
    Linux实用指令(5)
    C#中 char、byte、string
    编码转换
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10350610.html
Copyright © 2011-2022 走看看