jzoj 5864. 【NOIP2018模拟9.11】很多序列 数论

本文针对NOIP D1T1题目提供了一种详细的解题思路及代码实现。当n等于2时,直接给出计算公式。对于n大于2的情况,采用堆优化的方法求解最大可表示数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
这里写图片描述

Input
这里写图片描述

Output
这里写图片描述

Sample Input

2
4 7

Sample Output

17

Data Constraint
这里写图片描述

分析:
n=2n=2 就是noipD1T1,直接输出xyxyx∗y−x−y
考虑 n>2n>2 怎么做,此时x1<103x1<103
我们设k=x1k=x1a[i]a[i]为在mod kmod k意义下,余数为ii的最小的能被表示的数是多少。
因为有k这一个数,如果能表示出a[i]a[i],那么a[i]+ka[i]+k也能被表示出,答案其实就是(maxk1i=0a[i])k(maxi=0k−1a[i])−k
考虑怎样处理出aa,显然a0=0,然后依次加入第22个到第n个数。我们先把前i1i−1个数得到的ii放进一个堆里,每次弹出一个a[i]最小的数,判断能否去更新a[(i+d) mod k]a[(i+d) mod k],假设当前插入的是dd,如果能更新,就把这个新的也插入到堆里,这样就做完了。

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#define LL long long

const int maxn=1e5+7;

using namespace std;

LL n;
LL a[10],h[maxn];

struct rec{
    LL x,k;
};

bool operator <(rec a,rec b)
{
    return a.x>b.x;
}

priority_queue <rec> q;

int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    scanf("%lld",&n);
    for (LL i=1;i<=n;i++) scanf("%lld",&a[i]);
    if (n==2) printf("%lld",a[1]*a[2]-a[1]-a[2]);
    else
    {
        for (LL i=1;i<a[1];i++) h[i]=1e18;
        for (LL i=2;i<=n;i++)
        {
            for (LL j=0;j<a[1];j++) q.push((rec){h[j],j});
            while (!q.empty())
            {
                rec d=q.top();
                q.pop();
                LL k=d.k,l=(k+a[i])%a[1];
                if (h[l]>h[k]+a[i])
                {
                    h[l]=h[k]+a[i];
                    q.push((rec){h[l],l});
                }
            }
        }
        LL ans=0;
        for (LL i=0;i<a[1];i++) ans=max(ans,h[i]-a[1]);
        printf("%lld",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值