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

F.Tokitsukaze and Eliminate (hard)

题目:

2024牛客寒假算法基础集训营2(F、K、I、J)_第1张图片

解题思路:

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

代码如下:

#include 
#include 
#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;
        mapb;
        mapc;    //这里使用数组会超时,所以要考虑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<

K.Tokitsukaze and Password (easy)

题目:

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

2024牛客寒假算法基础集训营2(F、K、I、J)_第3张图片

解题思路:

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

代码如下:

#include 
#include 
#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;
        mapk;
        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='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<

 I.Tokitsukaze and Short Path (plus)

题目:

2024牛客寒假算法基础集训营2(F、K、I、J)_第4张图片

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

2024牛客寒假算法基础集训营2(F、K、I、J)_第5张图片

解题思路:

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

题目所求解为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 
#include 
#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<

J.Tokitsukaze and Short Path (minus)

题目:

2024牛客寒假算法基础集训营2(F、K、I、J)_第6张图片

2024牛客寒假算法基础集训营2(F、K、I、J)_第7张图片

解题思路:

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

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

代码如下:

#include 
#include 
#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

你可能感兴趣的:(算法)