【最短路】[JZOJ5864] 很多序列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzj1054689699/article/details/82669180

Description

这里写图片描述
这里写图片描述

Solution

这题咋一看。。NOIP2017D1T1的阴影仍然挥之不去。。。
找了一波规律,数论推了一波,什么都没有。。

事实上这题是道最短路题。。
观察数据范围,发现它比较猎奇
首先n=2我们直接用公式就是a*b-ab,去了NOIP2017都知道

最小的那个数很小,我们考虑在模x1下来做,对于模x1=p的某个位置,最小值以上都可以通过+x1来得到
问题就转化成模x1=p的某个位置最小能用另外几个数表示的数是什么

这就可以直接做最短路了。。。

Code

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 1005
#define LL long long
using namespace std;
LL a[6],f[N];
bool bz[N];
int n,d[100*N];
void spfa()
{
    d[1]=0;
    memset(f,107,sizeof(f));
    int l=0,r=1;
    f[0]=0;
    while(l<r)
    {
        int k=d[++l];
        fo(j,2,n)
        {
            int p=(k+a[j])%a[1];
            if(f[p]>f[k]+a[j]) 
            {
                f[p]=f[k]+a[j];
                if(!bz[p])
                {
                    bz[p]=1;
                    d[++r]=p;
                    if(f[p]<f[d[l+1]]) swap(d[l+1],d[r]);
                }
            }
        }
        bz[k]=0;
    }
}
int main()
{
    cin>>n;
    LL mx=0;
    fo(i,1,n) scanf("%lld",&a[i]);
    LL v=a[1]*a[2]-a[1]-a[2];
    if(n==2)
    {
        printf("%lld\n",v);
        return 0;
    }
    spfa();
    v=1;
    fo(i,0,a[1]-1) v=max(v,f[i]-a[1]);
    printf("%lld\n",v);
}

猜你喜欢

转载自blog.csdn.net/hzj1054689699/article/details/82669180
今日推荐