牛客小白月赛110【待补】

61 阅读2分钟
题目难度知识点
A 智乃办赛签到
B 智乃的Wordle签到
C 智乃的数字★★打表/容斥+二分
D 智乃与长短期主义者博弈★★区间DP

image.png

智乃办赛

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
    int n; cin>>n;
    int cnt=n/500;
    if( n%500 == 0) cout<<char('A'+cnt-1)<<"500";
    else
    {
        cout<<char('A'+cnt);
        printf("%03d",n%500);
    }
    return 0;
}

智乃的Wordle

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int main() 
{
    string a,b; cin>>a>>b;
    map<char,int>mp;
    for(int i=0;i<a.size();i++) mp[a[i]]++;
    for(int i=0;i<a.size();i++)
    {
        if(a[i]==b[i]) cout<<'g';
        else if(a[i]!=b[i]&&mp[b[i]]) cout<<'y';
        else cout<<'r';
    }
    puts("");
    if(a==b) cout<<"congratulations";
    else cout<<"defeat";
    return 0;
}

智乃的数字

image.png

#include <bits/stdc++.h>
using namespace std;
bool check(int x)
{
    int w=x%10;
    if(w==5) return 1;
    int cnt=0;
    while(x) cnt+=(x%10),x/=10;
    if(cnt%3==0) return 1;
    return 0;
}
vector<int>ve;
int a[8]={0,2,4,6,6,4,2,6};
int s[8]={0,2,6,12,18,22,24,30};
int main() 
{
    /*for(int i=1;i<=1000;i+=2) if(check(i)) ve.push_back(i);
    for(int i=1;i<ve.size();i++) cout<<ve[i]-ve[i-1]<<endl;*/
    int t; cin>>t;
    while(t--)
    {
        int k; cin>>k;
        k--;
        long long int ans=3;
        cout<<ans+(k/7)*30ll+s[k%7]<<'\n';
    }
    return 0;
}
//2,4,6,6,4,2,6=30

容斥+二分

image.png

image.png

image.png

image.png

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
LL check(LL x)
{
    return x/3+x/5-x/6-x/10-x/15+x/30;
}
void solve(int x)
{
    LL l=3,r=1e18;
    while(l<r)
    {
        LL mid=(l+r)/2;
        if(check(mid)<x) l=mid+1;
        else r=mid;
    }
    cout<<l<<endl;
}
int main(void)
{
    int t; cin>>t;
    while(t--)
    {
        int n; cin>>n;
        solve(n);
    }
    return 0;
}

智乃与长短期主义者博弈

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int f[N][N],a[N],n,sum;
//f[i][j] 指的是[i,j]区间内,长期的最大值.
int main(void)
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
    memset(f,-0x3f,sizeof f);
    for(int i=1;i<=n;i++) f[i][i]=0;
    for(int i=2;i<=n;i++) f[i-1][i]=min(a[i-1],a[i]);
    for(int len=3;len<=n;len++)
    {
        for(int i=1;i<=n;i++)
        {
            int l=i,r=i+len-1;
            if(r>n) break;
            if(a[l]>=a[r]) f[l][r]=max(f[l+1][r-1]+a[r],f[l+2][r]+a[l+1]);
            else f[l][r]=max(f[l][r-2]+a[r-1],f[l+1][r-1]+a[l]);
        }
    }
    cout<<sum-f[1][n]<<" "<<f[1][n];
    return 0;
}

动态规划+记忆化搜索

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int f[N][N],a[N],n,sum;
//f[i][j] 指的是[i,j]区间内,长期的最大值.
int dfs(int l,int r)
{
    if(l==r)
    {
        f[l][r]=0;
        return f[l][r];
    }
    if( r-l+1 == 2)
    {
        f[l][r]=min(a[l],a[r]);
        return f[l][r];
    }
    if(f[l][r]!=-1) return f[l][r];
    int ans=0;
    if(a[l]>=a[r])
    {
        ans=max(ans,dfs(l+2,r)+a[l+1]);
        ans=max(ans,dfs(l+1,r-1)+a[r]);
    }else
    {
        ans=max(ans,dfs(l,r-2)+a[r-1]);
        ans=max(ans,dfs(l+1,r-1)+a[l]);
    }
    f[l][r]=ans;
    return f[l][r];
}
int main(void)
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
    memset(f,-1,sizeof f);
    int ans=dfs(1,n);
    cout<<sum-ans<<" "<<ans;
    return 0;
}