1. 程式人生 > >ISIJ 2018 很多序列(Training Round D4T3) 最短路+數學

ISIJ 2018 很多序列(Training Round D4T3) 最短路+數學

Description

給定n個遞增正整數,求不能由這些數字線性組合表示出的最大正整數 其中x1106nx21011+nxn12+ngcd(x1,x2)=1

Solution

noip要是考成這樣真得回家種田了⊙﹏⊙∥ 注意到n=2的情況就是NOIP2017D1T1的數學題 我們發現x1很小,考慮簡化剩餘系來做。 建立x1個點,對於第a個點向(a+xi)%x1連權值為xi的邊跑最短路 考慮dis[a]的含義,顯然表示模x1餘a的最小能組成的數字。於是最大的dis[a]-x1就是答案了

Code

#include <stdio.h>
#include <string.h>
#include <queue>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)

typedef long long LL;
const LL INF=1000000000000000000;
const int N=2000005;

bool vis[N];

LL dis[N];
LL a[7],wjp;

int spfa(int n) {
    std
:: queue <int> que; rep(i,1,a[1]) dis[i]=INF; que.push(0); vis[0]=true; for (;!que.empty();) { int now=que.front(); que.pop(); rep(i,2,n) { int tar=(a[i]%a[1]+now)%a[1]; if (dis[now]+a[i]<dis[tar]) { dis[tar]=dis[now]+a[i]; if
(!vis[tar]) { que.push(tar); vis[tar]=true; } } } vis[now]=false; } LL ans=0; rep(i,0,a[1]) if (dis[i]!=INF) ans=std:: max(ans,dis[i]-a[1]); printf("%lld\n", ans); } int main(void) { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); int n; scanf("%d",&n); rep(i,1,n) scanf("%lld",&a[i]); if (n==2) { printf("%lld\n", a[1]*a[2]-a[1]-a[2]); return 0; } spfa(n); return 0; }