题意,给一些数,问最大的不能被这些数表示出来的数(自由相加)是多少。(大凯的疑惑)
解法
一个想法是dp,然后对答案有影响的上界接近于最大数的平方。
这个和noip 2018 d1t2也差不多
另一个做法是先选择这些数中的一个数,我们为了方便就选最小的一个mn,然后可以发现如果可以表示出x,那么
x
+
m
n
,
x
+
2
×
m
n
,
x
+
3
×
m
n
x+mn,x+2\times mn,x+3\times mn
x+mn,x+2×mn,x+3×mn等都是可以被表示出来的,所以我们将其它的数按对mn取模的值分类。这样就可以对[0,mn-1]这里面的每个数
i
i
i 计算最小的可以被原数列表示出来的数,同时对
m
n
mn
mn 取模等于
i
i
i .然后再这些最小值里取一个最大的,就是答案了。
然后怎么求这些最小值呢,这里可以使用最短路的方法,将每个数看成一条边进行转移(这里和dp有点像)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
inline int read(){
char c=getchar();int t=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
return t*f;
}
int n,m,a[maxn],mn,alfa[maxn],cnt,mp[maxn];
typedef pair<int,int> pii;
vector<pii> e[maxn];
inline void add(int a,int b,int c){
e[a].push_back(pii(b,c));
}
priority_queue<pii,vector<pii>,greater<pii> > q;
int dis[maxn],vis[maxn];
const int inf=0x3f3f3f3f;
void dj(){
for(int i=1;i<mn;i++){dis[i]=-1;}
q.push(pii(0,0));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
// while(vis[u]){u=q.top().second;q.pop();}
vis[u]=1;
pii v;int l=e[u].size();
for(int i=0;i<l;i++){
v=e[u][i];//printf("%d %d\n",u,v.first);
if((dis[v.first]==-1)||(dis[v.first]>dis[u]+v.second)){
dis[v.first]=dis[u]+v.second;
q.push(pii(dis[v.first],v.first));
}
}
}
}
int main(){
//freopen("8.in","r",stdin);
//freopen("8.out","w",stdout);
n=read();//m=read();
mn=0x3f3f3f3f;
for(int i=1;i<=n;i++){
a[i]=read();
// for(int j=a[i];j>=max(1,a[i]-m);j--){mp[j]=1;}
}
/* for(int i=1;i<=3000;i++){
if(mp[i]){alfa[++cnt]=i;}
}
n=cnt;mn=3001;
for(int i=1;i<=n;i++){
a[i]=alfa[i];
//printf("%d\n",a[i]);
}*/
for(int i=1;i<=n;i++){
if(mn>a[i])mn=a[i];
}
// printf("%d\n",mn);
for(int i=0;i<mn;i++){
for(int j=1;j<=n;j++){
// printf("%d %d\n",i,(i+a[j])%mn);
add(i,(i+a[j])%mn,a[j]);
}
}
dj();
int mx=0,flag=1;
for(int i=0;i<mn;i++){
if((dis[i]==-1)||(dis[i]-mn>inf)){flag=0;break;}
// printf("%d %d\n",i,dis[i]);
mx=max(mx,dis[i]);
}
if(!flag){puts("0");}
else{
printf("%d\n",max(mx-mn,0));
}
return 0;
}
(这里有些注释的代码是因为这本来是另一道题,但是双倍经验了)
这个的复杂度
O
(
n
∗
m
i
n
(
a
[
i
]
)
+
n
l
o
g
(
n
)
)
O(n*min(a[i])+nlog(n))
O(n∗min(a[i])+nlog(n)),比dp快很多