8/17 牛客训练营9补题+cf(BC)

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8/17 牛客训练营9补题+cf(BC)相关的知识,希望对你有一定的参考价值。

B-Two Frogs

题意:两只青蛙从荷叶1跳到荷叶n,每个荷叶可跳的范围是(i,i+a[i]](左开右闭),问两只青蛙跳到荷叶n的概率是多少?
所用知识:前缀和、差分、dp
思路:
1.设计状态dp[i][j]:表示所用j步跳到荷叶i的概率是多少
2.状态的转移:当前青蛙可跳的荷叶数为(i,i+a[i]],共有a[i]个荷叶可供选择。因此这段区间dp[i+1~i+a[i]][j+1]的概率都为dp[i][j]/a[i].
3.由此可看出是区间值得累加,因此想到差分。dp[i+1][j+1]加上概率dp[i][j]/a[i],而dp[i+a[i]+1][j+1]则减去概率dp[i][j]/a[i]
4.在每次对dp[i][j]进行操作时,要写一个for循环进行前缀和得累加。

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=8e3+5;;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int n,a[N],b[N],dp[N][N];
int qpow(int x,int y)

    int res=1;
    while(y)
    
        if(y&1)
            res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    
    return res;


void solve()

    cin>>n;
    for(int i=1;i<n;i++)
        cin>>a[i],b[i]=qpow(a[i],mod-2);
    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][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;
        
    
    int ans=0;
    for(int i=1;i<n;i++)
        ans=(ans+dp[n][i]*dp[n][i]%mod)%mod;
    cout<<ans<<endl;

signed main()

    //ios;
    solve();
    return 0;


G-Two Frogs

题意:给定n个字符串,问有多少个回文串的数量出现在这n个字符串中?
所用知识:马拉车算法、哈希算法

思路:
1.先采用双哈希算法来降低字符串记录数值的冲突
2.在采用马拉车算发记录有多少本质不同的回文串。
3.减枝。若当前字符串出现次数<id-1,则肯定不满足出现n次;
若出现次数等于n,则说明该字符串中已被统计过,无需重复记录。
若id>1,但还字符串还没出现过,统计次数为0,则无需统计。

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=7e5+6;;
const int inf=0x3f3f3f3f;
const int mod1=1000000007,mod2=998244353,base=131;
map<pair<int,int>,int>mp;
char ch[N],s[N];
//双哈希,进行两次哈希降低冲突
int sum1[N],sum2[N],pow1[N],pow2[N],n,G;
void init()

    pow1[0]=pow2[0]=1;
    for(int i=1;i<=300000;i++)
    
        pow1[i]=pow1[i-1]*base%mod1;
        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%mod1+s[i])%mod1;
        sum2[i]=(sum2[i-1]*base%mod2+s[i])%mod2;
        ch[i*2]=s[i];
        ch[i*2-1]='#';
    
    G=2*n+1;

pair<int,int> get_hash(int l,int r)

    int hash1 =(sum1[r] - sum1[l-1] * pow1[r - l + 1] % mod1 + mod1) % mod1;
    int hash2 =(sum2[r] - sum2[l-1] * pow2[r - l + 1] % mod2 + mod2) % mod2;
    return hash1, hash2;

//马拉车算法,求出多少个本质不同的回文子串
int r[N];
void manacher(int id)

    r[1]=1;
    int k=1;
    for(int i=2;i<=G;i++)
    
        int p=k+r[k]-1;
        if(i<=p)
            r[i]=min(r[2*k-i],p-i+1);
        else r[i]=1;
        while(ch[i-r[i]]==ch[i+r[i]]) r[i]++;
        if(i+r[i]>k+r[k])
        
            for(int rr=k+r[k]+1;rr<=i+r[i];rr++)
            
                int l=2*i-rr;
                if(ch[rr]=='#')
                
                    pair<int,int> hv=get_hash(l/2+1,rr/2);
                    if((id>1&&!mp.count(hv))||(mp[hv]==id))
                        continue;
                    if(id>1&&mp[hv]<id-1)
                    
                        mp.erase(hv);continue;
                    
                    mp[hv]=id;
                
            
            k=i;
        
    

void solve()

    init();
    cin>>n;
    for(int i=1;i<=n;i++)
    
        scanf("%s",s+1);
        init_str(s);
        manacher(i);
    
    int ans=0;
    for(auto x:mp)
        if(x.second==n)
            ans++;
    cout<<ans<<endl;

signed main()

    //ios;
    solve();
    return 0;


B. Mathematical Circus

这题确实有个点没想到。有点蒙蔽了,还老走神。。。。算想了个复杂的思路过的题。
思路:
1.将n个数分为4组,对4取模,0、1、2、3的分别为1组。
2.看似除了对2取模,其他输出1,2,3,4组中元素输出即可。
但其中是有规律的,但其中一个规律没找出来,导致做的很烦躁:
1.首先对4取模结果为0,是无法分组的:k不管和1、2、3谁组,都无法恰好分为2类
2.若对4取模结果为1,有两类分组情况,但其中一种情况是可行的:
第一类:(k+3组) 和 1组 形成pair 。 k+3组是可形成4的倍数,但不优。2组和4组形成一个pair
第二类:(k+2组) 和 2组 形成pair。看似没形成4的倍数,实则(k+2)组贡献了一个因子2,2组也天然带一个因子2.
第二类更优的情况是因为1组和2组形成pair,无需n是4的倍数。而第一类的前提条件是必须为4的倍数。

#include<bits/stdc++.h>
#define endl '\\n'
#define re register
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define maxn 1000000000LL
#define ULL unsigned long long
using namespace std;
const int N=7e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e7+7;
int n,k,a[N],b[N],c[N],d[N];
int g1,g2,g3,g4;

void solve()

    cin>>n>>k;
    g1=g2=g3=g4=0;
    for(int i=1;i<=n;i++)
    
        if(i%4==1) a[++g1]=i;
        else if(i%4==2) b[++g2]=i;
        else if(i%4==3) c[++g3]=i;
        else if(i%4==0) d[++g4]=i;
    
    if(k%4==0)
    
        cout<<"NO"<<endl;
    
    if(k%4==1)
    
        cout<<"YES"<<endl;
        for(int i=1;i<=g1;i++)
            cout<<a[i]<<" "<<b[i]<<endl; // 3 1
        for(int i=1;i<=g3;i++)
            cout<<c[i]<<" "<<d[i]<<endl; // 2 4
    
    if(k%4==2)
    
        cout<<"YES"<<endl;
        for(int i=1;i<=g1;i++)
            cout<<b[i]<<" "<<a[i]<<endl;  // 2 1
        for(int i=1;i<=g3;i++)
            cout<<c[i]<<" "<<d[i]<<endl;  // 3 4
    
    if(k%4==3)
    
        cout<<"YES"<<endl;
        for(int i=1;i<=g1;i++)
            cout<<a[i]<<" "<<b[i]<<endl; // 1 2
        for(int i=1;i<=g3;i++)
            cout<<c[i]<<" "<<d[i]<<endl; // 3 4
    

signed main()

    int t;cin>>t;
    while(t--)
        solve();
    return 0;


C. Fighting Tournament

B题想复杂了,导致C题没心情去看。。。

#include<bits/stdc++.h>
#define endl '\\n'
#define re register
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define maxn 1000000000LL
#define ULL unsigned long long
using namespace std;
const int N=7e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e7+7;
int n,q,p,k,a[N],mx[N],l[N];
map<int,int>mp;
void solve()

    cin>>n>>q;
    int g=0,pos;
    for(int i=1;i<=n;i++)
    
        cin>>a[i];
        if(a[i2021牛客暑期多校训练营1(部分补题)

暑期补题计划Orz

19香港补题(G)+cf思维

2021牛客暑期多校训练营2.I Penguins BFS广搜 简单

2017-8-17训练日记

2021牛客暑期多校训练营9