2020牛客多校第二场 A , J 题

J题
Just Shuffle
题意:已知置换 e = {1,2,…,n } 变换k次后得到一个置换a(已知),求置换e变换一次得到的置换x。
题解:这题我们能想到,对于变换规则,会存在一些环,意味着变换环的大小后置换不变。我们针对每个环考虑,设环的大小为len,变换一次的状态等价于变换 len * y + 1 次,那我们从已知考虑,已知变换k次后的状态,那么我们就能推出变换 2 * k ,3 * k,4 * k , … , 次后的状态( 我们将变换k次当成一单位次的变换 )。那我们猜想如果 x * k = len * y + 1, 方程两边同时 % len , 方程变成 x * k % len = 1;解这个方程,可以枚举答案,利用逆元的定义,答案在 0 - len -1 之间。


#include
#define ll long long
using namespace std;
const int maxn = 1e5+10;
int a[maxn];
int vis[maxn],ans[maxn],to[maxn];
vector<int> G;
void dfs(int p)
{
    vis[p] = 1;
    G.push_back(a[p]);
    if(!vis[to[p]])
    {
        dfs(to[p]);
    }
}
void go(int k)
{
    int len = G.size() ,inv;
    for(int i=0;i<len;i++) if((ll)i*k%len==1) { inv = i; break; }
    for(int i=0;i<len;i++)
        ans[G[i]] = G[(i+inv)%len];
}
int main()
{
       int n,k; scanf("%d%d",&n,&k);
       for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),to[i] = a[i];
      for(int i=1;i<=n;i++)
      {
          G.clear();
          if(!vis[i])
          {
              dfs(i);
              go(k);
          }
      }
      for(int i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n");
}


A题
All with Pairs
题解:将每个字符串的后缀hash值保存起来,用双hash值来减冲突,然后枚举每个前缀,在hash_map中找后缀,但是需要去重,对于两个aaa来说,我枚举a ,aa ,aaa时,另一个aaa都计算了贡献,而只能计算aaa的贡献,因为要最长。我们发现如果我们计算了aaa的贡献,那么必然也要计算a 和 aa的贡献,这样就重复了,所以这其实就是一个字符串next数组,我们只需要减去next数组的贡献就行了。

#include
#define ll long long
using namespace std;
const int maxn = 1e6+10;
ll base[2] = {43,47};
ll mod[2] = {1000000007,998244353} , h[3][maxn];
ll f[2][maxn];
void init()
{
     f[0][0] = f[1][0] = 1;
     for(int i=1;i<maxn;i++)
        for(int j=0;j<2;j++) f[j][i] = f[j][i-1] * base[j] % mod[j];
}
ll gets(int l,int r,int id)
{
    return (h[id][r] - h[id][l-1] * f[id][r-l+1] % mod[id] + mod[id]) % mod[id];
}
const ll mood=1e9+7;
const int maxsz=3e6+7;
template<typename key,typename val>
class hash_map{public:
  struct node{key u;val v;int next;};
  vector<node> e;
  int head[maxsz],nume,numk,id[maxsz];
  int geths(pair<ll,ll> &u){
    int x=(1ll*u.first*mood+u.second)%maxsz;
    if(x<0) return x+maxsz;
    return x;
  }
  val& operator[](key u){
    int hs=geths(u);
    for(int i=head[hs];i;i=e[i].next)if(e[i].u==u) return e[i].v;
    if(!head[hs])id[++numk]=hs;
    if(++nume>=e.size())e.resize(nume<<1);
    return e[nume]=(node){u,0,head[hs]},head[hs]=nume,e[nume].v;
  }
  void clear(){
    for(int i=0;i<=numk;i++) head[id[i]]=0;
    numk=nume=0;
  }
};
hash_map<pair<ll,ll>,ll> mp;
string s[maxn];
int nt[maxn];
void getnext(string ss)
{
    int k = -1 , j = 0;
    int n = ss.size();
    nt[0] = -1;
    while(j<n)
    {
        if(k==-1||ss[j]==ss[k])
        {
            j++; k++;
            nt[j] = k;
        }
        else k = nt[k];
    }
}
ll cnt[maxn];
const ll modd =998244353;
int main()
{
     std::ios::sync_with_stdio(false);
     init();
     int n ;
     cin>>n;
     for(int i=1;i<=n;i++) cin>>s[i];

     for(int i=1;i<=n;i++)
     {
         int len = s[i].size();
         for(int j=0;j<len;j++)
         {
             int tmp = s[i][j] - 'a' + 1;
             for(int k=0;k<2;k++)
                h[k][j+1] = ( h[k][j] * base[k] % mod[k] + tmp ) % mod[k];
         }

         pair<ll,ll> tmp;
         for(int j=1;j<=len;j++)
         {
             tmp.first = gets(j,len,0);
             tmp.second = gets(j,len,1);
             mp[tmp]++;
         }
     }

     for(int i=1;i<=n;i++)
     {
          int  len = s[i].size();
          for(int j=0;j<len;j++)
          {
              int tmp = s[i][j] - 'a' + 1;
              for(int k=0;k<2;k++)
                h[k][j+1] = ( h[k][j] * base[k] % mod[k] + tmp ) % mod[k];
          }
          getnext(s[i]);
           pair<ll,ll> tmp;

          for(int j=len;j>=1;j--)
          {
               tmp.first = gets(1,j,0);
               tmp.second = gets(1,j,1);
               int xx = mp[tmp];
               cnt[j] += xx;
               cnt[j] %= modd;
               cnt[nt[j]] = ( cnt[nt[j]] - xx + modd ) % modd;
          }

     }
     ll ans = 0;
    // for(int i=1;i<=10;i++) cout<
     for(int i=1;i<maxn;i++)
     {
         ans = ( ans + ( cnt[i] * ( (ll)i*i % modd ) ) % modd  ) % modd;
     }
     cout<<ans<<endl;

}

你可能感兴趣的:(字符串,思维题)