winter week3 day3

2024牛客寒假算法基础集训营3

A智乃与瞩目狸猫、幸运水母、月宫龙虾

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    string a,b;
    cin>>a>>b;
    int c='a'-'A';
    if(a[0]>='A'&&a[0]<='Z')a[0]+=c;
    if(b[0]>='A'&&b[0]<='Z')b[0]+=c;
    if(a[0]==b[0])cout<<"Yes\n";
    else cout<<"No\n";
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

B智乃的数字手串

思路:好像说是直接判n奇偶就行,刚开始有猜过但是没敢这样写hh。

要求相邻数和为偶数才能操作,那把所有数分两类奇和偶。当奇偶交替出现,且有偶数个数时是败局。那就要尽可能消除连续的奇偶性相同的数,记要消除的总个数为a。

交换的话,若两个数奇偶相同,交换的话没有意义。若不同,枚举所有情况可发现最后的可操作相邻对数只会偶数倍增减,增减偶数次操作相当于结果没变,那就没必要交换。

消除完后剩下的数,判断是否需要再操作一次使得个数为偶,需要的话消除总个数再加一

最后在判断a的奇偶性即可

(qwq奇是qcjj啦

-----------

看了题解,还是考虑败局的情况,当长度为奇数时,一定是存在两个相邻数和为偶数的,那就直接判长度奇偶就可以了

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n,c=0;
    cin>>n;
    vector<int>ve(n);
    for(int i=0;i<n;++i){
        cin>>ve[i];
        if(i&&ve[i]==ve[i-1])c++;
    }
    if((n-c)%2)c++;
    if(c%2)cout<<"qcjj\n";
    else cout<<"zn\n";
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

智乃的前缀、后缀、回文

思路:回文串要满足翻转后和原串相等,且需pres=suft,pret=sufs,那就在前后缀相等的串中找出所有前缀回文串,然后要pres和sufs不覆盖的话可以二分/双指针去求答案都可以。用字符串哈希判断是否为回文串,暴力试了发也过了qwq

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};


void solve() {
    int n,m;
    cin>>n>>m;
    string x,y;
    cin>>x>>y;
    std::reverse(x.begin(), x.end());
    vector<int>pre(min(n,m)+5),suf(min(n,m)+5);
    string xx,yy,z;
    for(int i=0;i<min(n,m);++i){
        xx.push_back(x[i]);
        yy.push_back(y[i]);
        z.insert(z.begin(),x[i]);
        if(xx!=yy)break;
//        string t=xx;
//        std::reverse(t.begin(), t.end());
        if(z==xx)pre[i]=i+1;
    }
    xx.clear(),yy.clear(),z.clear();
    std::reverse(x.begin(), x.end());
    std::reverse(y.begin(), y.end());
    for(int i=0;i<min(n,m);++i){
        xx.push_back(x[i]);
        yy.push_back(y[i]);
        if(xx!=yy)break;
//        string t=xx;
//        std::reverse(t.begin(), t.end());
        z.insert(z.begin(),x[i]);
        if(z==xx)suf[min(n,m)-i-1]=i+1;
    }
    int ans=-1;
    for(int i=1;i<min(n,m);++i){
        pre[i]=max(pre[i-1],pre[i]);
    }
    for(int i=min(n,m)-2;i>=0;--i){
        suf[i]=max(suf[i+1],suf[i]);
    }
    for(int i=0;i<min(n,m)-1;++i){
        if(pre[i]>0&&suf[i+1]>0)ans=max(ans,pre[i]+suf[i+1]);
    }
    if(ans>0)cout<<2*ans;
    else cout<<-1;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}
查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
vector<int>h1,h2,p;
int base=233;
int n;
bool check(int l,int r){
    if(h1[r]-h1[l-1]*p[r-l+1]==h2[n-l+1]-h2[n-r+1-1]*p[r-l+1])return true;
    return false;
}
void solve() {
    int x,y;
    string a,b;
    cin>>x>>y>>a>>b;
    std::reverse(a.begin(), a.end());
    string s=" ";
    for(int i=0;i<min(x,y);++i){
        if(a[i]!=b[i])break;
        s.push_back(a[i]);
        n++;
    }
    h1=h2=p=vector<int>(n+5),(n+5),(n+5);
    p[0]=1;
    for(int i=1;i<=n;++i){
        h1[i]=h1[i-1]*base+(ull)s[i];
        h2[i]=h2[i-1]*base+(ull)s[n-i+1];
        p[i]=p[i-1]*base;
    }
    vector<int>ans1,ans2;
    for(int i=1;i<=n;++i){
        if(check(1,i))ans1.push_back(i);
    }
    s=" ";
    n=0;
    std::reverse(a.begin(), a.end());
    std::reverse(b.begin(), b.end());
    for(int i=0;i<min(x,y);++i){
        if(a[i]!=b[i])break;
        s.push_back(a[i]);
        n++;
    }
    p=h2=h1=vector<int>(n+5,0);
    p[0]=1;
    for(int i=1;i<=n;++i){
        h1[i]=h1[i-1]*base+(ull)s[i];
        h2[i]=h2[i-1]*base+(ull)s[n-i+1];
        p[i]=p[i-1]*base;
    }
    for(int i=n;i>=1;--i){
        if(check(1,i))ans2.push_back(i);
    }

    if(ans1.empty()||ans2.empty()){
        cout<<-1;
        return ;
    }
    int ans=-1;
    for(auto l:ans1){
        int r=min(x,y)-l;
        auto it= lower_bound(ans2.begin(),ans2.end(),r,greater<int>());
        if(it!=ans2.end())ans=max(ans,l+*it);
        else break;
    }
    if(ans==-1)cout<<ans;
    else cout<<2*ans;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

Dchino's bubble sort and maximum subarray sum(easy version)

思路:k最大为2,那就狠狠暴力啦

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n,k;
    cin>>n>>k;
    vector<int>ve(n),s;
    for(int i=0;i<n;++i)cin>>ve[i];
    s=ve;
    int ans=0;
    if(k==1){
        for(int i=0;i<n-1;++i){
            swap(ve[i],ve[i+1]);
            int x=0;
            for(int j=0,c=0;j<n;++j){
                if(c+ve[j]>0)c+=ve[j];
                else c=0;
                x=max(x,c);
            }
            ans=max(ans,x);
            ve=s;
        }
    }else{
        int x=0;
        for(int i=0,c=0;i<n;++i){
            if(c+ve[i]>0)c+=ve[i];
            else c=0;
            x=max(x,c);
        }
        ans=max(ans,x);
    }
    if(ans==0){
        int x=ve[0];
        for(int i=1;i<n;++i)x=max(x,ve[i]);
        ans=x;
    }
    cout<<ans;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

G智乃的比较函数(easy version)

思路:n最大为2,直接判就可以。

判断下给定条件的相反条件是否成立即可。

若x<y成立,那x>=y和y<x就不能成立

若x>=y成立,那x<y就不能成立

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n;
    cin>>n;
    bool ok=true;
    vector<vector<int>>ve(4,vector<int>(4));
    for(int i=0;i<n;++i){
        int x,y,z;
        cin>>x>>y>>z;
        if(x==y&&z==1)ok=false;
        if(x==y)continue;
        if(z==0)z=-1;
        if(z==-1){
            if(ve[x][y]!=0&&ve[x][y]==1)ok=false;
        }else{
            if(ve[y][x]!=0&&ve[y][x]==1)ok=false;
            if(ve[x][y]!=0&&ve[x][y]==-1)ok=false;
        }
        ve[x][y]=z;
    }
    if(ok)cout<<"Yes\n";
    else cout<<"No\n";
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

H智乃的比较函数(normal version)

思路:n最大为50,但是点数只有3,还是判断所有的相反条件是否成立

若x<y成立,那x>=y和y<x就不能成立;有另一点z,x>=z&&z>=y、y<z&&z<x不能成立

若x>=y成立,那x<y就不能成立;有另一点z,x<z&&z<y不能成立

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};

struct E{
    int x,y,z;
};

void solve() {
    int n;
    cin>>n;
    bool ok=true;
    vector<E>g(n);
    vector<vector<int>>ve(4,vector<int>(4));
    for(int i=0;i<n;++i) {
        cin >> g[i].x >> g[i].y >> g[i].z;
        int x,y,z;
        x=g[i].x,y=g[i].y,z=g[i].z;
        if(z==0)z=-1;
        ve[x][y]=z;
    }
    for(int i=0;i<n;++i){
        int x,y,z;
        x=g[i].x,y=g[i].y,z=g[i].z;
        if(x==y&&z==1)ok=false;
        if(x==y)continue;
        if(z==0)z=-1;
        int zz=6-x-y;
        if(z==-1){
            if(ve[x][y]==1)ok=false;
            if(ve[x][zz]==1&&ve[zz][y]==1)ok=false;
        }else{
            if(ve[y][x]==1)ok=false;
            if(ve[x][y]==-1)ok=false;
            if(ve[x][zz]==-1&&ve[zz][y]==-1)ok=false;
            if(ve[y][zz]==1&&ve[zz][x]==1)ok=false;
        }
//        ve[x][y]=z;
    }
    if(ok)cout<<"Yes\n";
    else cout<<"No\n";
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

J智乃的相亲活动

思路:期望=第i个人被选上的概率*1=(1-第i个人没有被选上的概率pi)*1

记bij为第i个人的第j个心动对象(相互心动),第j个心动对象有cnt[bij]个心动对象,那么pij为第j个心动对象不选i的概率,pij=(cnt[bij]-1)/cnt[bij],那么pi=pi1*pi2*...*pij...

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<int>>ve(n+m+1);
    for(int i=0;i<k;++i){
        int u,v;
        cin>>u>>v;
        v+=n;
        ve[u].push_back(v);
        ve[v].push_back(u);
    }
    double ans1=0,ans2=0;
    for(int i=1;i<=n;++i){
        double s=1;
        for(auto v:ve[i]){
            double c=ve[v].size();
            s*=(c-1)/c;
        }
        ans1+=1-s;
    }
    for(int i=n+1;i<=n+m;++i){
        double s=1;
        for(auto v:ve[i]){
            double c=ve[v].size();
            s*=(c-1)/c;
        }
        ans2+=1-s;
    }
    cout<<"float\n";
    cout<<fixed<<setprecision(8)<<ans1<<' '<<ans2;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

 K智乃的“黑红树”

思路:构造的树为满二叉树时可以黑红节点数可以相差最大,当最后一层为黑时,a=2b+1;当最后一层为红时,b=2a;由此判断不可能构成红黑树的条件有a>2b+1和b>2a,还有当a为偶数或b为奇数时也不能构成。

若能构成,直接模拟黑红节点生成的红黑节点即可

查看代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};

void solve() {
    int a,b;
    cin>>a>>b;
    if(b%2||a%2==0||a>2*b+1||b>2*a){
        cout<<"No\n";
        return ;
    }
    cout<<"Yes\n";
    int n=a+b;
    vector<PII>ve(n+1,{-1,-1});
    a--;
    int l=1,r=1,now=2;
    while(a||b){
        for(int i=l;i<=r;++i){
            if(!b)break;
            ve[i]={now,now+1};
            now+=2,b-=2;
        }
        l=r+1,r=now-1;
        for(int i=l;i<=r;++i){
            if(!a)break;
            ve[i]={now,now+1};
            now+=2,a-=2;
        }
        l=r+1,r=now-1;
    }
    for(int i=1;i<=n;++i)cout<<ve[i].first<<' '<<ve[i].second<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

L智乃的36倍数(easy version)

思路:这个数据范围,当然先暴力

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n;
    cin>>n;
    vector<string>ve(n);
    int ans=0;
    for(int i=0;i<n;++i)cin>>ve[i];
    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j){
            if(i==j)continue;
            string c=ve[i]+ve[j];
            int cc= stoi(c);
            if(cc%36==0)ans++;
        }
    }
    cout<<ans;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

 

智乃的36倍数(normal version)

思路:

 酱酱,看完这些公式应该就比较好想了,记cnt[v]为v的位数,要找到f(x,y)%36==0,其实就是(x*10cnt[y]+y)%36==0,由上面的公式推得(x*10cnt[y]%36+y%36)%36==0,简化为(a+b)%36==0

可以预处理出f[i][j]表示乘上10j后对36取模为i的数的个数,那么对于每个y,可以直接求出b和a的个数,统计总的a的个数即为答案

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n;
    cin>>n;
    vector<int>ve(n);
    for(int i=0;i<n;++i)cin>>ve[i];
    vector<vector<int>>f(40,vector<int>(25));
    vector<int>g(30);
    g[0]=1;
    for(int i=1;i<=20;++i)g[i]=g[i-1]*10%36;
    for(int j=0;j<n;++j){
        for(int i=0;i<=19;++i){
            int x=((ve[j]%36)*g[i])%36;
            f[x][i]++;
        }
    }
    int ans=0;
    auto P=[](int x){
        int c=0;
        while(x){
            c++,x/=10;
        }
        return c;
    };
    for(int i=0;i<n;++i){
        int c=(36-ve[i]%36)%36;
        int cnt=P(ve[i]);
        int x=(((ve[i]%36)*g[cnt])%36+ve[i]%36)%36;
        if(x==0)ans--;
        ans+=f[c][cnt];
    }
    cout<<ans;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

 

posted @ 2024-02-08 00:17  bible_w  阅读(15)  评论(0编辑  收藏  举报