“蔚来杯“2022牛客暑期多校训练营9,签到题ABGIE

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“蔚来杯“2022牛客暑期多校训练营9,签到题ABGIE相关的知识,希望对你有一定的参考价值。

题号 标题 已通过代码 通过率 团队的状态
A Car Show 点击查看 1347/3168
B Two Frogs 点击查看 777/2832
C Global Positioning System 点击查看 41/136
D Half Turns 点击查看 9/28
E Longest Increasing Subsequence 点击查看 183/1423
F Matrix and GCD 点击查看 79/369
G Magic Spells 点击查看 461/3045
H Radar Scanner 点击查看 0/79
I The Great Wall II 点击查看 173/929
J Colourful Journey 点击查看 2/25
K NIO’s OAuth2 Server 点击查看 70/282

文章目录

A.Car Show

链接:https://ac.nowcoder.com/acm/contest/33194/A
来源:牛客网

题目描述
There are nn cities and mm car styles in NIO Kingdom. According to the investigations, for the ii-th city, cars of style T_iT
i

are the most popular.

Now there will be a car show in NIO Kingdom, and the person in charge wants to choose an integer interval [l,r][l,r] (1\\le l \\le r \\le n)(1≤l≤r≤n) and let the cities whose indices are in this interval hold the show jointly. And to manifest the variety of the cars, every style should occur at least once among the most popular styles in the host cities. Determine the number of integer intervals satisfying the constraint mentioned before.
输入描述:
The first line contains two integers nn and mm (1 \\le m \\le n \\le 100,000)(1≤m≤n≤100000), denoting the number of cities and the number of car styles respectively.

The second line contains nn integers T_1, T_2, \\cdots, T_nT
1

,T
2

,⋯,T
n

(1 \\le T_i \\le m)(1≤T
i

≤m), denoting the most popular styles.
输出描述:
Output one line containing one integer, denoting the answer.
示例1
输入
复制
5 3
1 2 3 2 1
输出
复制
5
说明
For the sample case, the 55 intervals are [1, 3], [1, 4], [1, 5], [2, 5], [3, 5][1,3],[1,4],[1,5],[2,5],[3,5] respectively.

题意:

  • 给定一个长为𝑛的包含1,2,…,𝑚的序列,求有多少区间[𝐿,𝑅]包含所有1,2,…,𝑚
    𝑚≤𝑛≤10^5。

思路:

  • 双指针,枚举左端点𝐿,合法的右端点集合一定是区间[𝑅,𝑛] ,且𝑅随着𝐿的递增而不减。
  • 在移动指针的同时维护区间内每种数字的个数以及出现数字的种类数 ,就可以在均摊𝑂(1)的时间对每个𝐿求出对应的𝑅。
  • 时间复杂度𝑂(𝑛)。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
int a[maxn], b[maxn];
int main()
    ios::sync_with_stdio(0), cin.tie(0),cout.tie(0);
    int n, m;  cin>>n>>m;
    for(int i = 1; i <= n; i++)cin>>a[i];
    set<int>se;
    LL ans = 0;
    for(int l=1, r=0; l <= n; l++)
        while(r<=n && se.size()<m)
            r++;
            se.insert(a[r]);
            b[a[r]]++;
        
        ans += n-r+1;  //对于当前的l, 从r开始包含所有1~m
        b[a[l]]--;     //l从当前区间去掉
        if(b[a[l]]==0)se.erase(a[l]);
    
    cout<<ans<<"\\n";
    return 0;



B.Two Frogs

链接:https://ac.nowcoder.com/acm/contest/33194/B
来源:牛客网

题目描述
In the Lonely Mountain, there are a lot of treasure well protected by dwarfs. Later, one day, the last dragon Smaug came and sensed the treasure being. As known to all, dragons are always much too greedy for treasure. So definitely, the war between dwarfs and Smaug begins.

During the war, two goblins Alice and Bob are turned into frogs by Gandalf, The Grey. In front of them, there are nn lotus leaves in a line. In order to break the spell, they must jump from the 11-st lotus leaf to the nn-th lotus leaf. If the frog is now on the ii-th lotus leaf instead of the nn-th lotus leaf, it can jump to a lotus leaf in range (i, i + a_i](i,i+a
i

].

Goblins are lack of intelligence and it’s also true even after turned into frogs. So Alice and Bob will jump randomly, which means, they will separately pick an available lotus leaf in every jump uniformly at random.

Since Alice and Bob have already being playing games for decades, so they want to know the probability that they jump to the nn-th lotus leaf with the same count of jumps.
输入描述:
The first line contains an integer nn (2 \\leq n \\leq 8,000)(2≤n≤8000), denoting the number of lotus leaf.

The second line contains n-1n−1 integers a_1, a_2, \\ldots, a_n-1a
1

,a
2

,…,a
n−1

, where the ii-th integer a_ia
i

(1 \\leq a_i \\leq n-i)(1≤a
i

≤n−i) indicates the range of lotus leaves that can be reached from the ii-th lotus leaf.
输出描述:
Output a line containing a single integer, indicating the probability that Alive and Bob jump to nn-th lotus leaf with the same count of jumps, taken modulo 998,244,353998244353.

Formally speaking, let the result, which is a rational number, be \\fracxy
y
x

as an irreducible fraction, you need to output x \\cdot y^-1 \\bmod998,244,353x⋅y
−1
mod998244353, where y^-1y
−1
is a number such that y \\cdot y^-1 \\equiv 1 \\pmod998,244,353y⋅y
−1
≡1(mod998244353). You may safely assume that such y^-1y
−1
always exists.
示例1
输入
复制
5
1 1 1 1
输出
复制
1
示例2
输入
复制
5
4 3 2 1
输出
复制
440198031

题意:

  • 河道里有𝑛个荷叶排成一排,从第𝑖(<𝑛)个荷叶出发可以跳到第(𝑖,𝑖+𝑎_𝑖]个荷叶上。
  • 有两只青蛙从第1个荷叶出发,每一步都独立地等概率随机地跳向后边的荷叶,求两只青蛙以相同步数到达第𝑛个荷叶的概率。
  • 𝑛≤8000,保证1≤𝑎_𝑖≤𝑛−𝑖。

思路:

  • 开始题意理解错了,去算了用i步到第j个点的方案数,所以样例怎么都算不出来。
    用了到达第n个点的,不同步数对应的方案数平方后加起来,所以第二个样例怎么算都是总共只有8种方案。
    但是题目事实上从第一个点跳到第二个点时的概率已经乘上了1/4,再从2号点出发往任何点跳都是带上了前面的系数和权重的,所以到最后的概率就不能简单的用方案数去乘。所以需要dp。
  • 𝑓(𝑠,𝑖)表示从第1个荷叶出发恰好𝑠次跳到第𝑖个荷叶的概率
    考虑向后转移,𝑓(𝑠,𝑖)对 𝑓(𝑠+1,𝑗) (𝑖<𝑗≤𝑖+𝑎𝑖) 有𝑓(𝑠,𝑖) ∕𝑎𝑖 的贡献,前缀和优化即可。
  • 复杂度O(n^2)
//时间优化
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 8010, mod = 998244353;
void exgcd(LL a, LL b, LL &d, LL &x,  LL & y, LL MOD)  if (b==0)  d = a; x = 1; y = 0;  else  exgcd(b, a % b, d, y, x, MOD); y -= x * (a / b);  
LL inv(LL a, LL MOD)  LL d=0, x=0, y=0; exgcd(a, MOD,  d,  x, y, MOD); return d == 1 ? (x + MOD) % MOD : -1; 

LL a[maxn], b[maxn], dp[maxn][maxn]; //到达位置i,走了j步的概率

int main()
    ios::sync_with_stdio(0), cin.tie(0),cout.tie(0);
    LL n;  cin>>n;
    for(int i = 1; i < n; i++)cin>>a[i], b[i]=inv(a[i],mod);
    dp[1][0] = 1;  dp[2][0] = -1;
    for(int i = 1; i <= n; i++)
        for(int k = 0; k < i; k++)
            //前缀和更新
            dp[i][k]=(dp[i][k]+dp[i-1][k])%mod;
            //转移:dp[i+1,i+a[i]][k+1] += dp[i][k]/a[i]
            dp[i+1][k+1]=(dp[i+1][k+1]+dp[i][k]*b[i])%mod;
            dp[i+a[i]+1][k+1]=(dp[i+a[i]+1][k+1]-dp[i][k]*b[i])%mod;
            // for(int j=i+1;j<=i+a[i];j++)
            //     dp[j][k+1]=(dp[j][k+1]+dp[i][k]*inv(a[i],mod)+mod)%mod;
            // 
        
    
    LL ans = 0;
    for(int i = 1; i < n; i++)ans = (ans+dp[n][i]*dp[n][i]%mod)%mod;
    cout<<ans<<"\\n";
    return 0;


//空间优化
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 8010, mod = 998244353;
void exgcd(LL a, LL b, LL &d, LL &x,  LL & y, LL MOD)  if (b==0)  d = a; x = 1; y = 0;  else  exgcd(b, a % b, d, y, x, MOD); y -= x * (a / b);  
LL inv(LL a, LL MOD)  LL d=0, x=0, y=0; exgcd(a, MOD,  d,  x, y, MOD); return d == 1 ? (x + MOD) % MOD : -1; 

LL a[maxn], b[maxn], dp[maxn];

int main()
    ios::sync_with_stdio(0), cin.tie(0),cout.tie(0);
    LL n;  cin>>n;
    for(int i = 1; i < n; i++)cin>>a[i], b[i] = inv(a[i],mod), a[i]=min(n,i+a[i])+1;
    LL ans = 0;
    dp[1] = 1;
    for(int i = 0; i <= n; i++)             //dp[j]:跳i次跳到第j个荷叶的概率
        ans = (ans+dp[n]*dp[n]%mod)%mod;
        dp[n] = 0;
        for(int j = n-1; j >= 0; j--)       //通过荷叶j来跳第i次,概率*1/a[j]
            LL t = dp[j]*b[j]%mod;           //概率+=dp[i-1][j]*1/a[j]
            dp[j+1] = (dp[j+1]+t+mod)%mod;   //给[j+1,j+a[j]] += t
            dp[a[j]] = (dp[a[j]]-t+mod)%mod; 
            dp[j] = 0;
        
        for(int j = 1; j <= n; j++)          //前缀和更新
            dp[j] = (dp[j]+dp[j-1])%mod;
        
    
    cout<<ans<<"\\n";
    return 0;



G.Magic Spells

链接:https://ac.nowcoder.com/acm/contest/33194/G
来源:牛客网

题目描述
One day in the magic world, the young wizard RoundDog was learning the compatibility of spells. After experimenting for a long time, he reached the conclusion that the compatibility of a spell collection can be measured by the number of distinct palindromes that are substrings of all the spells in the collection. He was so excited and planned to write a program to calculate the compatibility of any input spell collection.

However, RoundDog was busy participating the NowWizard Multi-Universe Training this week. He was too struggling during the competition and feels tired now.

Since RoundDog is not in the mood to finish the program now, could you help him?
输入描述:
The first line contains a single integer kk (1 \\leq k \\leq 5)(1≤k≤5), indicating the number of spells in a spell collection.

In the following kk lines, each line contains a spell SS (1 \\le |S| \\le 300,000)(1≤∣S∣≤300000), which is a string containing only lowercase English letters.

It is guaranteed that the total length of the spells does not exceed 300,000300000.
输出描述:
Output the compatibility of the input spell collection, which is the number of distinct palindromes that are substrings of all the spells in the collection.
示例1
输入
复制
3
abaca
abccaca
acabb
输出
复制
4
说明
In the example, “a”, “b”, “c”, “aca” are the four distinct palindromes that are substrings of all the input spells.

题意:

  • 给定𝑘个字符串𝑆_1,𝑆_2,…,𝑆_𝑘,求有多少个本质不同的公共回文子串
  • 𝑘≤5,|𝑆_𝑖|≤3×10^5

思路:

  • 因为k<=5,所以可以先对每个字符串𝑆分别求出所有本质不同回文子串,总共有𝑂(|𝑆|)个。
    可以使用Manacher算法配合Hash求解,也可以使用回文树求解。
  • Hash统计每个字符串的出现次数即可,时间复杂度𝑂(|𝑆|log⁡|𝑆|)或𝑂(|𝑆|(log⁡|S|+𝛴))。
  • 也可以直接回文自动机求解。
//manacher+hash
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 6e5+10;

char s[maxn];
map<pair<LL,LL>,int>mp; //字符串[l,r]的出现次数

//字符串双值hash(降低冲突)
const LL mod = 1000000007, mod2 = 998244353, base = 146;
char ch[maxn];
LL Sum1[maxn], Pow1[maxn], Sum2[maxn], Pow2[maxn], N;
void init()
    Pow1[0] = Pow2[0] = 1;
    for (int i = 1; i <= 300000; i ++)
        Pow1[i] = Pow1[i-1] * base % mod;
        Pow2[i] = Pow2[i-1] * base % mod2;
    

void init_str(char *s)
    int n = strlen(s + 1);
    ch[0] = '@';  ch[n*2+1] = '#';  ch[n*2+2] = '\\0';
    Sum1[0] = Sum2[0] =  0;
    for (int i = 1; i <=n; i++)
        Sum1[i] = (Sum1[i-1] * base % mod + s[i]) % mod;
        Sum2[i] = (Sum2[i-1] * base % mod2 + s[i]) % mod2;
        ch[i*2] = s[i];
        ch[i*2-1] = '#';
    
    N = 2*n+1;

inline pair<LL,LL> get_hash(int l, int r)
    LL hash1 = (Sum1[r] - Sum1[l-1] * Pow1[r - l + 1] % mod + mod) % mod;
    LL hash2 = (Sum2[r] - Sum2[l-1] * Pow2[r - l + 1] % mod2 + mod2) % mod2;
    return hash1, hash2;


//马拉车,求s的本质不同的回文子串
int r[maxn];
void manacher(int id)
    r[1] = 1;                                          //r[i]:以i为中心的最长回文子串
    int k = 1;
    for(int i = 2; i <= N; i++)
        int p = k+r[k]-1;
        if(i <= p)r[i] = min(r[2 * k - i], p - i + 1); //没有超过边界,用对称性求解
        else r[i] = 1;                                 //至少为1
        while(ch[i+r[i]] == ch[i-r[i]])r[i]++;         //超过边界时,暴力匹配
        //枚举以i为中心的回文串, k维护已经枚举过的边界
        if (i + r[i] > k + r[k])                      
            for (int R = k+r[k]+1; R <=i+r[i]; R++)
                int L = 2*i-R;
                //判断回文串[L,R], 如果次数<当前id,就去掉
                if(ch[R]=='#')
                    pair<LL,LL>hashvalue = get_hash(L/2+1,R/2);
                    if(id>1 && !mp.count(hashvalue))continue;
                    if(id>1 && mp[hashvalue]<id-1)
                        mp.erase(hashvalue);  continue;
                    
                    if(mp[hashvalue] == id)continue;
                    mp[hashvalue] = id;
                
            
            k = i;
        
    


int main()
    init();
    int n;  scanf以上是关于“蔚来杯“2022牛客暑期多校训练营9,签到题ABGIE的主要内容,如果未能解决你的问题,请参考以下文章

“蔚来杯“2022牛客暑期多校训练营2,签到题GJK

“蔚来杯“2022牛客暑期多校训练营7,签到题CFGJ

“蔚来杯“2022牛客暑期多校训练营10,签到题HFIE

“蔚来杯“2022牛客暑期多校训练营6,签到题GJBMA

“蔚来杯“2022牛客暑期多校训练营4,签到题NDKHL

“蔚来杯“2022牛客暑期多校训练营1,签到题GADI