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);
}
posted @ 2020-02-29 21:38  lemondinosaur  阅读(122)  评论(0编辑  收藏  举报