USACO 4.1
麦香牛块洛谷传送门,麦香牛块USACO传送门,篱笆回路洛谷传送门,篱笆回路USACO传送门
洛谷 2737 麦香牛块
分析
首先如果包装总GCD不为1,显然没有上界
然后这个答案如果存在必然满足在一个范围内,
可以推结论得到上界为\(max*(max-1)\)(好像是反证法)
然后就可以用完全背包求解啦,
但是为了推广\(\text{STL::bitset}O(\frac{n*maxlogLIMIT}{32})\)的做法
所以我就写了跑得更慢的做法T^T
代码
/*
ID:lemondi1
LANG:C++
TASK:nuggets
*/
#include <cstdio>
#include <algorithm>
#include <bitset>
#define rr register
using namespace std;
const int N=65300;
bitset<N>dp; int n,a[11],G,ans,lim;
inline signed gcd(int a,int b){return b?gcd(b,a%b):a;}
signed main(){
freopen("nuggets.in","r",stdin);
freopen("nuggets.out","w",stdout);
scanf("%d",&n);
for (rr int i=1;i<=n;++i){
scanf("%d",&a[i]);
G=gcd(G,a[i]);
}
if (G!=1) return !printf("0\n");
dp[0]=1,sort(a+1,a+1+n),lim=a[n]*(a[n]-1);
for (rr int i=1;i<=n;++i)
for (rr int j=a[i];j<=lim;j<<=1)
dp|=dp<<j;
dp[0]=0;
for (rr int i=a[n]*(a[n]-1);~i;--i)
if (!dp[i]) return !printf("%d\n",i);
}
洛谷 2738 篱笆回路
分析
显然是求最小环,数据小用\(\text{FLOYD}\)解决
但是建图是关键,考虑用哈希存下某篱笆某一边所有可连的篱笆(包括它自己)
这样就可以加点了
代码
/*
ID:lemondi1
LANG:C++
TASK:fence6
*/
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <map>
#define rr register
using namespace std;
typedef unsigned uit; map<uit,int>uk;
int d[101][101],dis[101][101],n,ans,a[11];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
freopen("fence6.in","r",stdin);
freopen("fence6.out","w",stdout);
memset(dis,42,sizeof(dis)),
memset(d,42,sizeof(d)),ans=d[0][0];
for (rr int Test=iut();Test;--Test){
rr int Num=iut(),Len=iut(),X[2];
rr int nn[2]={iut(),iut()},Tot;
for (rr int j=0;j<2;++j){
a[Tot=1]=Num;
for (;nn[j];--nn[j])
a[++Tot]=iut();
sort(a+1,a+1+Tot);
rr uit h=a[1];
for (rr int i=2;i<=Tot;++i)
h=h*137+a[i];
if (!uk[h]) uk[h]=++n;
X[j]=uk[h];
}
dis[X[0]][X[1]]=d[X[0]][X[1]]=Len;
dis[X[1]][X[0]]=d[X[1]][X[0]]=Len;
}
for (rr int k=1;k<=n;++k){
for (rr int i=1;i<k-1;++i)
for (rr int j=i+1;j<k;++j)
ans=min(ans,dis[i][j]+d[i][k]+d[j][k]);
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
return !printf("%d\n",ans);
}