寒假训练第3周(牛客冬训营)

F-Tokitsukaze and Eliminate (hard)_2024牛客寒假算法基础集训营2 (nowcoder.com)

脑袋堵住了,红温没有写出来,后面想到思路直接给否定了,可惜

题解:需要你找最右边第一个,直接先统计一下有多少个颜色的宝石,然后从左往右依次放入set到相应的颜色数就加答案,然后如果这种颜色宝石没有了就需要把一开始统计数减一下即可,后面继续放到set就好了

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n'
using namespace std;
const int N=1e6+10,M=1e1;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

int a[N];
set<int> b;
map<int,int> mp;
void solve()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        mp[a[i]]++;
    }
    int l=mp.size();
    int ans=0;
    int c=0;
    for(int i=n;i>=1;i--)
    {
        b.insert(a[i]);
        mp[a[i]]--;
        if(mp[a[i]]==0) c++;
        if(b.size()==l)
        {
            ans++;
            l-=c;
            c=0;
            b.clear();
        }
    }
    cout<<ans<<endl;
    mp.clear();
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 D-Tokitsukaze and Slash Draw_2024牛客寒假算法基础集训营2 (nowcoder.com)

这是一道图论题 迪杰斯特拉 想法很好,当时没有想到,一眼以为dp

题解:这道题我们可以把每一个卡牌的位置看成一个个点,然后呢,我们直接从k跑到n的一个最短路搞成一个图即可,至于怎么更新

这里就是用到dp思维了,用代价去更新,尽量寻找代价最低即可

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n'
using namespace std;
const int N=1e6+10,M=1e1;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;



void solve()
{
    int n,m,k;
    cin>>n>>m>>k;
    priority_queue<PII,vector<PII>,greater<PII>> q;
    PII a[N];
    for(int i=0;i<m;i++)
    {
        int x,y;
        cin>>x>>y;
        a[i]={x,y};
    }
    vector<int> b(n+1,LLONG_MAX);

    b[k-1]=0;
    q.push({0,k-1});
    while (q.size())
    {
        auto [x,dian]=q.top();
        q.pop();
        if(b[dian]<x) continue;
        for(int i=0;i<m;i++)
        {
            auto [next,w]=a[i];
            next+=dian;
            next%=n;
            if(b[next]>w+x)
            {
                b[next]=w+x;
                q.push({b[next],next});
            }
        }
    }
    if(b[n-1]==LLONG_MAX) b[n-1]=-1;
    cout<<b[n-1]<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 K-Tokitsukaze and Password (easy)_2024牛客寒假算法基础集训营2 (nowcoder.com)

这是一道比较简单的题 当时没有看 一道直接暴力就行 数据范围小

题解:我们直接遍历a b c d _ 把每一个值都遍历出来,然后把他转换成一个数字 在对题目的条件判断即可,纯暴力

但是求导0的问题要注意 这里我们直接不能小于n位数的最小值即可 就是可以判掉前导0

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e6+10,M=1e1;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

set<int> all;

void solve()
{
    all.clear();
    int n;
    cin>>n;
    string s;
    cin>>s;
    int y;
    cin>>y;
    int minn;
    if(n>1) minn=pow(10,n-1);
    if(n==1) minn=0;
    for(int a=0;a<10;a++)
    {
        for(int b=0;b<10;b++)
        {
            for(int c=0;c<10;c++)
            {
                for(int d=0;d<10;d++)
                {
                    if(a==b || b==c || c==d || a==c || a==d || b==d) continue;
                    for(int k=0;k<10;k++)
                    {
                        int x=0;
                        for(int i=0;i<n;i++)
                        {
                            if(s[i]>='0' && s[i]<='9' )x=10*x+(s[i]-'0');
                            if(s[i]=='a') x=x*10+a;
                            if(s[i]=='b') x=x*10+b;
                            if(s[i]=='c') x=x*10+c;
                            if(s[i]=='d') x=x*10+d;
                            if(s[i]=='_') x=10*x+k;

                        }
                        if(x%8==0 && x<=y && x>=minn) all.insert(x);
                    }
                }
            }
        }
    }
    cout<<all.size()<<endl;

}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 M-智乃的36倍数(normal version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

赛时这道题相出了一个解法,但是没有实现,就是36=4*9,然后就把两个数加起来判断是否满足模4==0模9==0

模9==0每一个数字相加等于9的倍数  模4等于0后两位可以被4整除 分别统计就可以了

 

接下来是另外一种思路

题解:

 所以我们可以知道,直接分开模两个数字就可以了

然后我们先处理前面的数字,就是你要乘上多少倍放前面,我们提前把最小都模36,比如1e18模36=28然后我们就统计18位数的时候是乘28不用去乘上1e18,等于提前模36

然后我们map统计每一个数字模36的个数

枚举1到35  j

和每一个数字拼起来,然后mp[j],有就加上没有就加0就可以了,j*c[len[i]] 相当于前面的数字就是组合的第一个数

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e6+10,M=1e1;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

int a[N];

void solve()
{
    int n;
    cin>>n;
    int c[20]={0};
    int t=10;
    map<int,int> mp;
    for(int i=1;i<=18;i++)
    {
        c[i]=t%36;
        t*=10;
    }
    int len[n+1];
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        string s= to_string(a[i]);
        len[i]=s.size();
        a[i]%=36;
        mp[a[i]]++;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<36;j++)
        {
            if((j*c[len[i]]+a[i])%36==0)
            {
                ans+=mp[j];
                if(j==a[i]) ans--;
            }
        }
    }
    cout<<ans<<endl;

}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 H-智乃的比较函数(normal version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

又是一道暴力的意想不到题。。。

题解:我们直接枚举1 2 3    3 2 1    2 1 3   等这些情况,然后看看有没有一钟情况满足给出的限制条件,满足的话就说明限制条件不矛盾,枚举这些情况即可,就是直接拿来按照题目意思比大小啦  赋值比大小

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e6+10,M=1e1;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

vector<array<int,3>> cmp;
int a[N];
int ans;
void check()
{
    int res=0;
    for(auto [x,y,z]:cmp)
    {
        if(z==0){
            if(a[x]<a[y]) res=1;
        }
        if(z==1)
        {
            if(a[x]>=a[y]) res=1;
        }
    }
    if(res==0) ans=1;
}
void solve()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        cmp.push_back({x,y,z});
    }
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            for(int k=1;k<=3;k++)
            {
                a[1]=i,a[2]=j,a[3]=k;
                check();
            }
        }
    }
    if(ans==1) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    ans=0;
    cmp.clear();
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 

posted @ 2024-02-05 20:06  whatdo+  阅读(11)  评论(0编辑  收藏  举报