2024牛客暑期多校训练营第六场


赛时解决题目:A,B,H

目录

赛时解决题目:A,B,H

H:

        题意:

        解题思路:

B:

        题意:

        解题思路:

A:

        题意:

        解题思路:

F:图论(构造)

        题意:

D:tanjan

        解题:



H:

        题意:抽卡游戏,签到题

        解题思路:记录10连出四星以上,90连出保底,还有大保底判一下就行。

                

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
void solve()
{
    string s;cin>>s;
    ll a[6]={0};
    ll cnt90=0,cnt10=0;
    bool ret=0;
    ll ans=1;
    for(auto i:s)
    {
        cnt90++;
        cnt10++;
        if(i=='4'||i=='5'||i=='U')cnt10=0;
        if(i=='5')
        {
            if(ret==1)
            {
                ans=0;break;
            }else
                ret=1,cnt90=0;
        }
        if(i=='U')
        {
            cnt90=0;
            ret=0;
        }
        if(cnt90==90||cnt10==10)ans=0;
    }
    if(ans)
        cout<<"valid\n";
    else cout<<"invalid\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。



B:

        题意:奶奶买了一个大蛋糕。蛋糕的形状是正多边形。也就是说,一个所有内角相等且所有边相等的凸多边形。奶奶想把蛋糕切成一个漂亮的图案,和她的朋友们分享。她以逆时针的顺序将顶点0到n - 1编成索引,然后选择一个整数k。之后,她将蛋糕切割成n条直线,将顶点i和顶点(i+k)连接起来,每个i mod n。请帮她算一下。(有道翻译)

        解题思路:模拟一下发现就是正多边形,然后按照规律割线,注意一下会发现k肯定具有对称性,因此可以让k小于n的一半,又发现如果穿过中心点,是一种特殊情况,且只会出现在偶数正多边形,进行特判,最后手动模拟一下,k为2~n/2,会发现k每次加一,画出来的图就会多n块,结论就出来了。

        

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
void solve()
{
    ll n;cin>>n;
    ll k;cin>>k;
    if(k>n/2)
    {
        k=n-k;
    }
    if(n%2==0&&k==n/2)
    {
        cout<<n<<'\n';
    }else
    {
        ll ans=n+1;
        ans+=(k-1)*n;
        cout<<ans<<'\n';
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;

    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。




A:

        题意:我也没想过这题目信息量挺大),有A人和B人两个人分蛋糕,然后他们有个分蛋糕的方式,首先给一棵现成的树,根节点为1,给你n个点,和n-1条边,边权值要么是1要么是0。两个人轮流走,A先走,从根节点开始,选取当前点的子节点中的一个,捡起边权值1或0,直到走到终点。这样把路径上的1,0拼起来成了一个01字符串,长度假设为m。那么这时B人要把蛋糕任意切成m份(也可以是空的几份)然后两个人按照01字符串的规则,如果是数字1,那么A人从分出来的蛋糕中挑一块,如果是0则B去挑一块。问A人最多能吃蛋糕几分之几。

        解题思路:A肯定希望早拿和多拿1,B也是,那么dfs跑一下就行,对于每个01串,ans只需要取个min即可,因为蛋糕是由B去切成块的,而他们肯定都先拿大的,所以B肯定切出来是均等的有效块数。那么对于每轮进行贪心A想要ans大,B想要ans小,递归即可。

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
ll a[N];
vector<ll>go[N];
map<PLL,ll>mp;
double dfs(ll u,ll fa,ll ret,double cnt0,double cnt1,double ans)
{
    if(cnt0+cnt1>=1)ans=min(ans,cnt1/(cnt0+cnt1));
    double res=ans;
    if(go[u].empty())
    {
        return res;
    }
    bool ru=0;
    for(auto i:go[u])
    {
        if(i==fa)continue;
        if(!ru)
        {
            if(ret)ans=dfs(i,u,ret^1,cnt0+(mp[{min(u,i),max(i,u)}]==0),cnt1+(mp[{min(u,i),max(i,u)}]==1),res);
            else ans=dfs(i,u,ret^1,cnt0+(mp[{min(u,i),max(i,u)}]==0),cnt1+(mp[{min(u,i),max(i,u)}]==1),res);
            ru=1;
            continue;
        }
        if(ret)ans=max(dfs(i,u,ret^1,cnt0+(mp[{min(u,i),max(i,u)}]==0),cnt1+(mp[{min(u,i),max(i,u)}]==1),res),ans);
        else ans=min(dfs(i,u,ret^1,cnt0+(mp[{min(u,i),max(i,u)}]==0),cnt1+(mp[{min(u,i),max(i,u)}]==1),res),ans);
    }
    res=ans;
    return res;
}
void solve()
{
    ll n;
    cin>>n;
    for(int i=1; i<=n; i++)a[i]=0,go[i].clear();
    for(int i=1; i<n; i++)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        if(u>v)swap(u,v);
        go[u].eb(v);
        go[v].pb(u);
        mp[{u,v}]=w;
    }
    cout<<fixed<<setprecision(13)<<dfs(1,-1,1,0,0,1)<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。



F:图论(构造)

        题意:给一个树林,然后问这树林的补图存不存在哈密尔顿路径。

哈密尔顿路径:经过所有点,且每个点只经过一次。

补图:补图中存在边的两点,在原图中不存在边

解题思路:会发现点数在2,3时需要特判一下,剩下的必然树的直径是大于4的,那么可以根据深度进行分层,会发现奇数层和偶数层可以几乎任意的去接,而同一层的点也可以随意接在一起(因为题目保证没有环)。这时候就需要判断一下只有一圈的菊花图,因为连完树枝后,没有点可以连到中点,但因为题目是树林,所以可以把这个点接到下一棵树的脑袋上。

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define N (int)3e5+10
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨

void solve()
{
    int n,m;
    cin>>n>>m;
    vector<vector<int>>G(n+1);
    for(int i=0;i<m;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].eb(y);
        G[y].eb(x);
    }
    if(n==2)
    {
        if(m==0)
            cout<<"1 2\n";  /// 补图是唯一的哈密尔顿路径
        else
            cout<<"-1\n";
    }
    else if(n==3)
    {
        if(m==0)
            cout<<"1 2 3\n";
        else if(m==2)
        {
            cout<<"-1\n";
        }
        else if(m==1)
        {
            if(G[1].size()&&G[3].size())
            {
                cout<<"1 2 3\n";
            }
            else if(G[1].size()&&G[2].size())
            {
                cout<<"1 3 2\n";
            }
            else if(G[2].size()&&G[3].size())
            {
                cout<<"2 1 3\n";
            }
        }
    }
    else      // n>=4
    {
        vector<int>vis(n+1),dist(n + 1);
        int mxidx=0;
        auto dfs=[&](auto self,int u,int fa)->void
        {
            if(dist[u]>dist[mxidx])mxidx=u;
            vis[u]=true;
            for(auto it:G[u])
            {
                if(it==fa)
                    continue;
                else
                {
                    dist[it]=dist[u]+1LL;
                    self(self,it,u);
                }
            }
        };
        vector<PLL>v;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                mxidx=i;
                dfs(dfs,i,0ll);
                dist[mxidx]=0ll;
                int u=mxidx;
                dfs(dfs,mxidx,0ll);
                v.push_back({u,mxidx});
            }
        }
        auto add=[&](int u,int v)->void
        {
            G[u].eb(v);
            G[v].eb(u);
        };
        for (int i=1;i<v.size();i++)
        {
            add(v[i-1].ss,v[i].ff);
        }
        dist[v[0].ff] = 0;
        mxidx=v[0].ff;
        dfs(dfs,mxidx,0);
        int I=dist[mxidx]+1LL;
        if (I<=3)
        {
            cout<<"-1\n";
        }
        else
        {
            vector<vector<int>>VE(dist[mxidx]+2LL);
            for(int i=1;i<=n;i++)VE[dist[i]+1LL].eb(i);
            for (int i=I-1;i>=1;i-=2)
            {
                for (auto x:VE[i])cout<<x<< " ";
            }
            for (int i=I;i>=1;i-=2)
            {
                for (auto x:VE[i])cout<<x<<" ";
            }
            cout<<"\n";
        }
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。



D:tanjan

        解题:(我去学了一波tanjan(强连通分量),交了洛谷的板子题),下面是洛谷题的代码:消息扩散

#include<bits/stdc++.h>
#define endl '\n'
#define ll int
#define int int
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
vector<ll>go[N];
ll dfn[N];
ll cnt;
stack<ll>st;
ll vis[N];///看某个点是否入栈
ll low[N];
ll _cnt;
ll sum[N];///强连通分量权值记录
ll belong[N];///该点属于哪个强连通分量
ll sig[N];///强连通分量可到标记点
void tanjan(ll u)
{
    cnt++;
    dfn[u]=low[u]=cnt;
    st.push(u);
    vis[u]=1;
    for(auto i:go[u])
    {
        if(dfn[i]==0)
        {
            tanjan(i);
            low[u]=min(low[u],low[i]);
        }
        else if(vis[i])///如果i在栈中,那么i一定是u的祖先节点
        {
            low[u]=min(low[u],dfn[i]);
        }
    }
    if(low[u]==dfn[u])
    {
        _cnt++;
        while(st.top()!=u)
        {
            sum[_cnt]++;///加的是权值
            vis[st.top()]=0;
            belong[st.top()]=_cnt;
            st.pop();
        }
        sum[_cnt]++;///他本身的权值
        belong[u]=_cnt;
        vis[u]=0;
        st.pop();
    }
}
void solve()
{
    ll n,m;cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        ll u,v;cin>>u>>v;
        go[u].pb(v);
    };
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            tanjan(i);
    }
    for(int u=1;u<=n;u++)
    {
        for(auto v:go[u])
        {
            if(belong[u]!=belong[v])
            {
                sig[belong[v]]=1;
            }
        }
    }
    ll ans=0;
//    cout<<_cnt<<'\n';
    for(int i=1;i<=_cnt;i++)
    {
        ans+=(sig[i]==0);
    }
    cout<<ans<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。



这边放D题AC代码

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
vector<ll>go[N];
ll dfn[N];
ll cnt;
stack<ll>st;
ll ins[N];///看某个点是否入栈
ll low[N];
ll _cnt;
ll sum[N];///强连通分量权值记录
ll belong[N];///该点属于哪个强连通分量
ll sig[N];///强连通分量可到标记点
ll n,m;
vector<PLL>lun;
vector<PLL>qie;
vector<PLL>ans;
void tanjan(ll u,ll fa)
{
    cnt++;
    dfn[u]=low[u]=cnt;
    st.push(u);
    ins[u]=1;
    for(auto i:go[u])
    {
//        cout<<"r="<<i<<'\n';
        if(i==fa)continue;
        if(dfn[i]==0)
        {
            tanjan(i,u);
            low[u]=min(low[u],low[i]);
        }
        else if(ins[i]==1)///如果i在栈中,那么i一定是u的祖先节点
        {
            low[u]=min(low[u],dfn[i]);
        }
    }
    if(low[u]==dfn[u])
    {
        _cnt++;
        while(st.top()!=u)
        {
            sum[_cnt]++;///加的是权值
            ins[st.top()]=2;
            belong[st.top()]=_cnt;
            st.pop();
        }
        sum[_cnt]++;///加的是权值
        ins[st.top()]=2;
        belong[st.top()]=_cnt;
        st.pop();
    }
}
ll fa[N];
ll find(ll x)
{
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}
void solve()
{
    cin>>n>>m;
    for(int i=1; i<=m; i++)
    {
        ll u,v;
        string w;
        cin>>u>>v>>w;
        if(w=="Lun")
        {
            go[u].pb(v);
            go[v].pb(u);
            lun.eb(u,v);
        }
        else
            qie.eb(u,v);
    };
    for(int i=1; i<=n; i++)
    {
        fa[i]=i;
        if(!ins[i])
            tanjan(i,0);
    }
    for(auto [u,v]:lun)
    {
        if(belong[u]==belong[v])ans.eb(u,v);
    }
    for(auto [u,v]:qie)
    {
        if(find(belong[u])!=find(belong[v]))
        {
            ans.eb(u,v);
            fa[find(belong[v])]=find(belong[u]);
            _cnt--;
        }
    }
    if(_cnt==1)
    {
        cout<<"YES\n";
        cout<<ans.size()<<'\n';
        for(auto [u,v]:ans)
        {
            cout<<u<<' '<<v<<'\n';
        }
    }
    else cout<<"NO\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值