牛客周赛 Round 103 (全解)

不太想做牛客周赛的题解,毕竟题解很快就给出了。这次写是为了警示我以后都用自然溢出去hash

A.清楚

思路:判断最后一位是不是0即可

#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main(){
    fio();
    ll t=1;
    // cin>>t;
    while(t--){
        ll n;
        cin>>n;
        if(n-n/10*10==0)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}

B.姐姐

思路:全相同最好判断,随后就是只要判断连续0或连续1在环中是连续的即可,直接倍增,将链变环.走一遍看看即可

#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main(){
    fio();
    ll t=1;
    cin>>t;
    while(t--){
        ll n;
        cin>>n;
        vector<ll>a(2*n+4);
        ll cnt=0;
        ll c=0;
        for(ll i=1;i<=n;i++)cin>>a[i],cnt+=(a[i]==a[1]),c+=(a[i]==1);
        // for(ll i=n)
        if(cnt==n)cout<<"YES"<<endl;
        else {
            for(ll i=n+1;i<=2*n;i++)a[i]=a[i-n];
            ll len=c;
            bool f=0;
            for(ll i=1;i<=n*2;i++){
                if(a[i])len--;
                else len=c;
                if(len==0){
                    f=1;
                    break;
                }
            }
            cout<<(f==1?"YES":"NO")<<endl;
        }
    }
    return 0;
}

C.智乃

思路:手枚举下,不完全归纳得出答案为2^(n-1).

#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main(){
    fio();
    ll t=1;
    // cin>>t;
    while(t--){
        ll n;
        cin>>n;
        // vector<ll>a(2*n+4);
        cout<<ksm(2,n-1)<<endl;
    }
    return 0;
}

D.哥哥

思路:先看有没有至少三个(答案为0)。然后看有没有两个(答案为1),然后看有没有一个(答案为1或2,走一遍试试看看能不能一次操作解决即可(能就1否则就2)),如果都没有直接2次

#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main(){
    fio();
    ll t=1;
    cin>>t;
    while(t--){
        ll n;
        string f;
        cin>>n>>f;
        ll cnt=0;
        for(ll i=0;i<f.size();i++){
            cnt+=(f[i]==f[0]);
        }
        if(cnt==n){
            cout<<2<<endl;
        }
        else {
            cnt=0;
            for(ll i=1;i<f.size();i++){
                if(f[i]!=f[i-1])cnt++;
            }
            if(cnt>=3)cout<<0<<endl;
            else {
                ll ans=0;
                for(ll i=0;i<f.size();i++){
                    bool flag=0;
                    if(i>0){
                        if(f[i]!=f[i-1])flag=1;
                    }
                    if(i<f.size()-1){
                        if(f[i]!=f[i+1])flag=1;
                    }
                    if(flag==0){
                        ll cc=0;
                        if(i>0)cc++;
                        if(i<f.size()-1)cc++;
                        ans=max(ans,cnt+cc);
                    }
                }
                if(ans<=2)cout<<2<<endl;
                else cout<<1<<endl;
            }
        }
    }
    return 0;
}

E.新婚

思路:如果从一个点往上走会比较好想,最多走个21 * n次,然后记录下这个路径上的二进制,然后倒着和正着扫一遍(注意不要越界哦),打上标记即可.查询O(q)

#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main(){
    fio();
    ll t=1;
    // cin>>t;
    while(t--){
        ll n,q;
        cin>>n>>q;
        string f;
        cin>>f;
        f='0'+f;
        vector<vector<ll>>g(n+2);
        vector<ll>fa(n+2);
        for(ll i=1;i<n;i++){
            ll l,r;
            cin>>l>>r;
            g[l].push_back(r);
            g[r].push_back(l);
        }
        vector<bool>vis((1ll<<20)+1,0);
        function<void(ll,ll)>dfs=[&](ll x,ll fc){
            fa[x]=fc;
            ll len=21;
            ll now=x;
            vector<ll>ls;
            while(len--){
                if(now==0)break;
                ls.push_back((f[now]=='1'));
                now=fa[now];
                ll c1=0,c2=0;
                ll l=1;
                for(ll i=0;i<ls.size();i++){
                    c1+=ls[i]*l;
                    c2+=ls[ls.size()-i-1]*l;
                    l<<=1;
                }
                if(c1<=(1ll<<20))vis[c1]=1;
                if(c2<=(1ll<<20))vis[c2]=1;
                // vis[c1]=vis[c2]=1;
            }
            for(auto j:g[x]){
                if(j==fc)continue;
                else dfs(j,x);
            }
        };
        dfs(1,0);
        // cout<<
        while(q--){
            ll x;
            cin>>x;
            cout<<(vis[x]?"YES":"NO")<<endl;
        }
    }
    return 0;
}   

F.快乐

思路:hash,显然最长公共前缀的贡献,可以等价于该前缀的前缀连续子串的出现次数。所以先hash一遍求出所有前缀连续字串的出现次数,然后再走一遍做m个字符串前缀连续字串贡献累加。最后对目标串进行字符串hash,随后根据对应字符串hash求法(直接查段值),遍历+二分,找当前左端点能有值的最右端点即可。(用自然溢出,不用取模会更快,还有就是用数组的二分会比map更快)

吐槽:赛时不用自然溢出,经历了Wa和Tle

#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
// const ll mod = 1e9 + 7;
const ull p=1145161651561;
// ll ksm(ll x, ll y)
// {
//     ll ans = 1;
//     while (y)
//     {
//         if (y & 1)
//         {
//             ans = ans * x % mod;
//         }
//         x = x * x % mod;
//         y >>= 1;
//     }
//     return ans % mod;
// }
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main(){
    fio();
    int t=1;
    cin>>t;
    while(t--){
       int n,m;
       cin>>n>>m;
       string str,f[m+2];
       cin>>str;
       str='0'+str;
       map<ull,ll>mp;
       for(int i=1;i<=m;i++){
        cin>>f[i];
        ull hash=0;
        for(int j=0;j<f[i].size();j++){
            hash=hash*p+f[i][j];
            mp[hash]++;
        }
       }
       map<ull,ll>an;
       vector<ull>dd;
       for(int i=1;i<=m;i++){
        ull hash=0;
        ll pre=0;
         for(int j=0;j<f[i].size();j++){
            hash=hash*p+f[i][j];
            pre+=mp[hash];
            if(an.find(hash)==an.end()){
            dd.push_back(hash);
            an[hash]=pre;
            }
         }
       }
       sort(dd.begin(),dd.end());
       ull hash=0;
       vector<ull>pre(n+5,0);
       for(int i=1;i<str.size();i++){
        hash=hash*p+str[i];
        pre[i]=hash;
       }
       vector<ull>us(n+5);
       us[0]=1;
       for(ll i=1;i<=n;i++){
        us[i]=us[i-1]*p;
       }
       function<ll(int,int)>ck=[&](int x,int y){
        ull ans=pre[y]-pre[x-1]*us[y-(x-1)];
        ll j=lower_bound(dd.begin(),dd.end(),ans)-dd.begin();
        if(j!=dd.size()&&dd[j]==ans)return 1ll;
        else return 0ll;
       };
       ll ans=0;
       for(int i=1;i<str.size();i++){
        int l=i,r=str.size()-1;
        while(l<=r){
            int mid=l+r>>1;
            if(ck(i,mid)){
                l=mid+1;
            }
            else r=mid-1;
        }
        ull ac=pre[r]-pre[i-1]*us[r-(i-1)];
        ans=max(ans,an[ac]);
       }
       cout<<ans<<endl;
    }
    return 0;
}   
posted @ 2025-08-03 21:15  长皆  阅读(52)  评论(0)    收藏  举报