USACO 4.1

偶尔善良 提交于 2020-02-29 22:53:23

麦香牛块洛谷传送门麦香牛块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);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!