2023河南萌新联赛第一场:河南农业大学 部分题解

本篇题解只有:A、D、E、F、G、H、J、K、L(后续学会B、C、I 会补上去的

出题人预估难度:J<K<G<E<F<H<L<D<C<I<A<B
实际难度:J<E<G<K<F<A<H<L<D<I<C<B

目录

A   你也喜欢数学吗

D   松鼠回家

E   动物朋友

F   松鼠排序

G   Reverse

H   迷宫探险

J   合唱比赛

K   以撒和隐藏房间

L   中位数


A

你也喜欢数学吗

比赛时通过打表 直接推出公式

公式推导:

{\textstyle \sum_{i=1}^{n}} \varphi \left ( i \right ) \ast \left \lfloor n /i\right \rfloor = \frac{n\times \left ( n+1 \right ) }{2}

{\textstyle \sum_{i=1}^{k}}{\textstyle \sum_{i=1}^{n}} \varphi \left ( i \right ) \ast \left \lfloor n /i\right \rfloor = \frac{n\ast \left ( n+1 \right ) \ast \left ( n+2 \right ) }{6}

会爆long long注意取余,除法取余要用逆元

#include<bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int mod=1000000007;
int n,m;
string str;

int qmi(int a,int b,int q)
{
    int res=1%q;
    while(b)
    {
        if(b&1)res=res*a%q;
        a=a*a%q;
        b>>=1;
    }
    return res;
}

void solve()
{
	cin>>n;
    cout<<(((n%mod)*((n+1)%mod))%mod*(((n%mod)+2)%mod)%mod*qmi(6,mod-2,mod))%mod;
}

signed main()
{
	IOS
	int T=1;
	//cin>>T;
	while(T--) solve();
	
	return 0;
}

D

松鼠回家

根据题意求最大的那个点扣除的数量尽可能小 显然需要用到二分,二分最终扣除松果的数量 来找到最优满足解

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int N=1e5+10;
int n,m,st,ed,s;
int a[N];
string str;

int h[N],ne[N],e[N],w[N],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

int dist[N];
bool vis[N];
bool check(int mid)//dijkstra最短图
{
    mem(dist,0x3f);mem(vis,false);
    priority_queue<PII,vector<PII>,greater<PII> > q;
    q.push({0,st});
    dist[st]=0;
    if(a[st]>mid) return false;
    //当开始点扣除的松果数量大于mid,该情况不满足
    
    while(q.size())
    {
        auto t=q.top();
        q.pop();
        
        if(vis[t.second])continue;
        vis[t.second]=true;
        
        for(int i=h[t.second];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>t.first+w[i]&&a[j]<=mid)//每次到达的点扣除松果数应小于mid
            {
                dist[j]=t.first+w[i];
                q.push({dist[j],j});
            }
        }
    }
    //当最终点没办法到达 或 到底所需体力大于开始时候的体力 该情况不满足
    if(dist[ed]==0x3f3f3f3f||dist[ed]>s)return false;
    return true;
}


void solve()
{
    cin>>n>>m>>st>>ed>>s;
    for(int i=1;i<=n;i++)cin>>a[i];
    
    mem(h,-1);
    while(m--)
    {
        int x,y,z;
        cin>>x>>y>>z;
        add(x,y,z);
        add(y,x,z);//无向图
    }
    
    int l=1,r=(int)1e7;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    if(l==(int)1e7)cout<<"-1\n";
    else cout<<l<<"\n";
}

signed main()
{
    IOS
    int T=1;
    //cin>>T;
    while(T--) solve();
    
    return 0;
}

E

动物朋友

根据题意求 有多少种所选的连续的动物朋友的快乐值刚好为m,先预处理前缀和,再直接枚举每个动物,充当连续动物朋友的左边界,再使用二分找刚好满足的情况即可

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

int n,m;
string str;

void solve()
{
	cin>>n>>m;
    vector<int> a(n+1),s(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        s[i]=s[i-1]+a[i];
    }
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        int l=i,r=n;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(s[mid]-s[i-1]>=m)r=mid;
            else l=mid+1;
        }
        if(s[l]-s[i-1]==m)cnt++;
    }
    cout<<cnt;
}

signed main()
{
	IOS
	int T=1;
	//cin>>T;
	while(T--) solve();
	
	return 0;
}

F

松鼠排序

根据题意对于每个位置,在并查集中把 a[i]i 两个点合并,设最终合并大小为cnt,则即为答案。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int N=1e5+10;
int p[N];
int find(int x)
{
    return x==p[x]?p[x]:p[x]=find(p[x]); 
}
 
void solve()
{
    int n;cin>>n;
    for(int i=1;i<=n;i++)p[i]=i;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        int x;cin>>x;
        if(find(x)!=find(i))
        {
            p[find(x)]=find(i);
            cnt++;
        }
    }
    cout<<cnt;
}


signed main()
{
	IOS
	int T=1;
	//cin>>T;
	while(T--) solve();
	
	return 0;
}

G

Reverse

算是思维题吧

翻转后最长1长度 即为字符串连续的1数量 最大值和次大值相加之和

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int N=1e6+10;
int a[N];
int n,m,k;
string str;

void solve()
{
	cin>>n>>str;
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(str[i]=='1')
        {
            ans++;
        }
        else if(str[i]=='0')
        {
            a[k++]=ans;
            ans=0;
        }
    }
    if(ans)a[k++]=ans;
    sort(a,a+k,greater<int>());
    cout<<a[0]+a[1];
}

signed main()
{
	IOS
	int T=1;
	//cin>>T;
	while(T--) solve();
	
	return 0;
}

H

迷宫探险

正常bfs题,但中间加了一个跳板 ,可以直接跳w距离且不花时间,因此就要在分情况讨论了

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int N=3010;
int n,m,k,x,y,w,nx,ny;
char ma[N][N];
int dist[N][N];
string str;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
map<PII,int> mp;

void bfs()
{
    mem(dist,0x3f);
    queue<PII> q;
    q.push({1,1});
    dist[1][1]=0;
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        if(ma[t.first][t.second]=='.')
        {
            for(int i=0;i<4;i++)
            {
                nx=t.first+dx[i],ny=t.second+dy[i];
                //dist[nx][ny]<=dist[t.first][t.second]+1 走过已经走过的 即不再走 
                if(nx<1||nx>n||ny<1||ny>m||ma[nx][ny]=='#'||dist[nx][ny]<=dist[t.first][t.second]+1)continue;
                dist[nx][ny]=dist[t.first][t.second]+1;
                q.push({nx,ny});
            }
        }
        else
        {
            for(int i=0;i<4;i++)
            {
                nx=t.first+dx[i]*mp[{t.first,t.second}],ny=t.second+dy[i]*mp[{t.first,t.second}];
                if(nx<1||nx>n||ny<1||ny>m||ma[nx][ny]=='#'||dist[nx][ny]<=dist[t.first][t.second])continue;
                dist[nx][ny]=dist[t.first][t.second];
                q.push({nx,ny});
            }
        }
    }
}

void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>ma[i][j];
    cin>>k;
    while(k--)
    {
        cin>>x>>y>>w;
        mp[{x,y}]=w;
    }
    bfs();
    if(dist[n][m]==0x3f3f3f3f)cout<<"-1\n";
    else cout<<dist[n][m]<<"\n";
}

signed main()
{
    IOS
    int T=1;
    //cin>>T;
    while(T--) solve();
    
    return 0;
}

J

合唱比赛

真签到题

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

int n,m;
string str;

void solve()
{
	cin>>n;
    vector<int> a(n);
    for(int i=0;i<n;i++)cin>>a[i];
    sort(a.begin(),a.end());
    int sum=accumulate(a.begin(),a.end(),0);
    cout<<fixed<<setprecision(6)<<1.0*((sum-a[n-1])*1.0/(n-1))<<" ";
    cout<<fixed<<setprecision(6)<<1.0*((sum-a[0])*1.0/(n-1))<<" ";
}

signed main()
{
	IOS
	int T=1;
	//cin>>T;
	while(T--) solve();
	
	return 0;
}

K

以撒和隐藏房间

模拟题

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int N=1010;
char ma[N][N];
int n,m,c;
string str;

void solve()
{
    mem(ma,'3');
	cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>ma[i][j];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(ma[i][j]=='0')
            {
                int ans=0;bool ok=true;
                if(ma[i-1][j]=='1')ans++;
                if(ma[i+1][j]=='1')ans++;
                if(ma[i][j-1]=='1')ans++;
                if(ma[i][j+1]=='1')ans++;
                if(ma[i-1][j]=='2'||ma[i][j+1]=='2'||ma[i][j+1]=='2'||ma[i][j-1]=='2'||ma[i+1][j]=='2')ok=false;
                if(ans==3&&ok)c++;
            }
        }
    }
    if(c)cout<<"YES\n"<<c;
    else cout<<"NO\n";
}

signed main()
{
	IOS
	int T=1;
	//cin>>T;
	while(T--) solve();
	
	return 0;
}

L

中位数

算是树状数组的板子题了(如果会树状数组,就可以轻松解决

用数值数组维护每个数的个数,中位数即为k=(n+1)/2,也就是求第k大的数

有单调性,用二分可以轻松完成

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<"\n";
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
#define lowbit(x)  ((x) & - (x))
typedef pair<int,int> PII;
const double pi = acos(-1.);

const int N=1e6+10;
int n,m,a[N],tr[N];
string str;

void add(int x,int c)
{
    //这是要是N ,如果是n的话,会影响n-N之间的数,进而影响单调性
    for(int i=x;i<=N;i+=lowbit(i))tr[i]+=c;
}

int ask(int x)
{
    int res=0;
    for(int i=x;i;i-=lowbit(i))res+=tr[i];
    return res;
}

void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i],add(a[i],1);
    
    int k=(n+1)/2;
    while(m--)
    {
        int p,x;
        cin>>p>>x;
        add(a[p],-1);
        a[p]=x;
        add(x,1);
        int l=1,r=1e6;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(ask(mid)>=k)r=mid;
            else l=mid+1;
        }
        cout<<l<<"\n";
    }
}

signed main()
{
    IOS
    int T=1;
    //cin>>T;
    while(T--) solve();
    
    return 0;
}

如果有错误的地方,可以及时指出。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
你好!对于2023国赛C题:蔬菜类商品的自动定价与补货决策,下面是一种解题思路供参考: 1. 数据收集与预处理: - 收集蔬菜类商品的历史销售数据、进货数据、市场价格等信息。 - 对数据进行清洗和整理,包括去除异常值、缺失值处理等。 2. 价格模型建立: - 利用历史销售数据和市场价格信息构建合适的价格模型,可以考虑使用回归模型或时间序列模型等。 - 根据模型的预测结果,确定合适的定价策略,包括利润最大化、销售量最大化等。 3. 补货决策模型建立: - 根据蔬菜类商品的历史销售数据和进货数据,构建补货决策模型。 - 考虑到不同蔬菜类商品的生鲜特性和季节性变化,可以使用动态规划或者基于库存水平的决策方法。 4. 模型优化与调整: - 根据实际运营情况,对价格模型和补货决策模型进行不断优化和调整。 - 可以使用反馈机制,根据实际销售和补货情况来不断更新模型参数,以提高模型的准确性和适应性。 5. 系统开发与实施: - 基于以上模型和算法,开发一个蔬菜类商品的自动定价与补货决策系统。 - 系统可以实时监控销售情况、市场价格变化等,自动进行定价和补货决策,并生成报表和预测结果供参考。 在解题过程中,还需要考虑到不同蔬菜类商品的特点、市场竞争情况、供应链管理等因素,综合运用数据分析、优化算法和业务经验来实现有效的定价与补货决策。希望以上思路对您有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值