P1043 [NOIP2003 普及组] 数字游戏

原题链接

前记

1.环的问题可以转换成遍历以所有元素开头的链
2.对于某一条链,其最大值等于中间某两段最大值的乘积,这样就把大问题转换成了小问题

细节请看代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll pres[105]={0};
ll a[105]={0};
ll fmaxs[105][105][12];
ll fmins[105][105][12];//这里要定义成三维的,因为不知道某一区间的值是哪一层的
ll ssmax(ll l,ll r,ll layer)
{
    if(fmaxs[l][r][layer]!=-1)return fmaxs[l][r][layer];

    if(layer==1)
    {
        fmaxs[l][r][layer]=((pres[r]-pres[l-1])%10+10)%10;
        return fmaxs[l][r][layer];
    }

    ll ans=0;
    for(ll i=l+1;i<=r-(layer-1)+1;i++)  ans=max(ans,ssmax(l,i-1,1)*ssmax(i,r,layer-1));
    fmaxs[l][r][layer]=ans;
    return ans;
}

ll ssmin(ll l,ll r,ll layer)
{
    if(fmins[l][r][layer]!=-1)return fmins[l][r][layer];//记忆化

    if(layer==1)
    {
        fmins[l][r][layer]=((pres[r]-pres[l-1])%10+10)%10;//鬼知道什么求模
        return fmins[l][r][layer];
    }

    ll ans=2e9;
    for(ll i=l+1;i<=r-(layer-1)+1;i++)  ans=min(ans,ssmin(l,i-1,1)*ssmin(i,r,layer-1));//细节注意,layer-1代表下一层最少需要几个数字,+1代表下一层从哪个数开始
    fmins[l][r][layer]=ans;
    return ans;
}


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    memset(fmaxs,-1,sizeof fmaxs);
    memset(fmins,-1,sizeof fmins);
    ll n,m;
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
    {
        cin>>a[i];
        a[i+n]=a[i];//拆环成链
    }

    for(ll i=1;i<=2*n;i++)pres[i]=pres[i-1]+a[i];//求区间和==前缀和

    ll ansmax=0,ansmin=2e9;
    for(ll i=1;i<=n;i++)//环的问题等于以所有元素开头的链的问题
    {
        ansmax=max(ansmax,ssmax(i,i+n-1,m));
        ansmin=min(ansmin,ssmin(i,i+n-1,m));
    }

    cout<<ansmin<<endl<<ansmax;
    return 0;
}

posted @   纯粹的  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示