2024牛客寒假算法基础集训营2(F、K、I、J)

F.Tokitsukaze and Eliminate (hard)

题目:

解题思路:

对于总共有n个宝石,统计出不同的宝石有a个,从后往前取,则第一次取宝石可以取出a个不同的宝石,剩下不同的宝石有b个(b<=a),第二次再取出b个不同的宝石······最终统计一下次数即可。

代码如下:

#include <bits/stdc++.h>
#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{   ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,a[200005],sum=0,ans=0,k=0,j=0;
        map<int,int>b;
        map<int,int>c;    //这里使用数组会超时,所以要考虑stl容器
        cin>>n;
        for(int i=1;i<=n;i++)
            {cin>>a[i];
             if(b[a[i]]==0)sum++;    //统计不同宝石的总个数
             b[a[i]]++;}             //统计每个宝石的个数
        for(int i=n;i>=1;i--)
        {
            if(c[a[i]]==0)k++;    //统计不同宝石的个数
            c[a[i]]++;
            b[a[i]]--;
            if(b[a[i]]==0)j++;    //每当有宝石的个数为0时,总数要减去1
            if(k==sum)
                {sum-=j,j=0,ans++,k=0;
                 c.clear();    //清空}
        }
        cout<<ans<<endl;
    }
 	return 0;
}

K.Tokitsukaze and Password (easy)

题目:

解题思路:

此题可以直接暴力搜索,对a,b,c,d,_,进行整体考虑,最终会求出一个密码x,若满足题目所给条件及范围,则数量+1。

代码如下:

#include <bits/stdc++.h>
#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,y;
        string s;
        cin>>n;
        cin>>s>>y;
        int len=pow(10,n-1);    //求出这个位数的最小值,比如n=3时,最小值是100
        if(n==1)len=0;
        map<int,bool>k;
        for(int a=0; a<=9; a++)
        {
            for(int b=0; b<=9; b++)
            {
                for(int c=0; c<=9; c++)
                {
                    for(int d=0; d<=9; d++)
                    {
                        if(a==b||a==c||a==d||b==c||b==d||c==d)continue; //a,b,c,d不能相同
                        for(int _=0; _<=9; _++)
                        {
                            int x=0;
                            for(int i=0; i<n; i++)    //遍历出所有可能的结果
                            {
                                if(s[i]>='0'&&s[i]<='9')x=x*10+s[i]-'0';
                                else if(s[i]=='a')x=x*10+a;
                                else if(s[i]=='b')x=x*10+b;
                                else if(s[i]=='c')x=x*10+c;
                                else if(s[i]=='d')x=x*10+d;
                                else x=x*10+_;
                                if(x>=len&&x<=y&&x%8==0)    //若满足题目条件
                                    k[x]=1;
                            }
                        }
                    }
                }
            }
        }
        cout<<k.size()<<endl;
    }
    return 0;
}

 I.Tokitsukaze and Short Path (plus)

题目:

1<=T<=2\cdot 10^{5}(T组测试数据)

1<=N<=2\cdot 10^{5}(表示完全图G的顶点数量)

1<=a_{i}<=2\cdot 10^{5}(表示完全图G的每个顶点的值)

第二组测试数据:

3
10 1 100

解题思路:

对于此题使用最短路会超时,所以要先找规律,边权值为取两个点之间权值较大的那个权值的两倍。以下对第二组数据进行分析:

题目所求解为1->2,1->3,2->3,2->1,3->1,3->2,对此只需要求出前一半的值最后再乘上2就可以。接下来再对前一半进行分析:首先要对顶点进行排序,1->2取值为20,1->3取值为200,2->3取值为200,总结得顶点1的次数为0,顶点2的次数为1,顶点3的次数为2,得到公式sum+=a[i]*(i-1)*2;

代码如下:

#include <bits/stdc++.h>
#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{   ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,a[200005],sum=0;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        for(int i=n;i>=2;i--)
            sum+=a[i]*(i-1)*2;
        cout<<sum*2<<endl;
    }
 	return 0;
}

J.Tokitsukaze and Short Path (minus)

题目:

解题思路:

此题与上一题解法类似,只不过边权值为取两个点之间权值较小的那个权值的两倍。

对样例分析得到1->3取值有两种情况,一是直接取值,另一个是经过最小值点。

代码如下:

#include <bits/stdc++.h>
#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{   ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,a[200005],sum=0;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        for(int i=1;i<n;i++)
            sum+=min(a[1]*4,a[i]*2)*(n-i);
        cout<<sum*2<<endl;
    }
 	return 0;
}

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值