• TG 寒假-模拟 第二场 题解


    本场比赛较简单,恭喜xcy58神仙和chengxx神仙AK(热烈祝贺)。

    T1 水

    这题应该不难看出求n个瓶子最少可以合并为几个瓶子就是求二进制下的n有多少个1。

    然后就完了……每次增加一些瓶子,让新瓶子数在二进制一的数量下比原来的少就好。

    #include<iostream>
    using namespace std;
    unsigned long long n,a,b,shu=0,k=0;
    int main()
    {
    	cin>>a>>b;
    	while(1)
    	{
    		n=a;
    		shu=0;
    		while(n!=0)
    		{
    			if(n%2==1)
    			{
    				shu++;
    			}
    			n/=2;
    		}
    		if(shu<=b)
    		{
    			cout<<k<<endl;
    			return 0;
    		}
    		k+=(a&-a);
    		a+=(a&-a);
    	}
    	return 0;
    }
    

    (没用scanf,大佬轻喷)

    T2 朋友

    简单并查集,模板题……

    话说这题洛谷数据超级水,我故意写了好几个错的,洛谷全是满分(啊这)

    直接贴代码了

    #include<iostream>
    using namespace std;
    int z,n,m,a1,a2,a3,sz[1000005]; 
    int h(int zz)
    {
        if(sz[zz]==zz)return zz;
        return sz[zz]=h(sz[zz]);
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            sz[i]=i;
        }
        for(int i=0;i<m;i++)
        {
            cin>>a1>>a2>>a3;
            if(a1==1)
            {
                sz[h(a2)]=h(a3);
            }
            else if(a1==2)
            {
                if(h(a2)==h(a3))
                {
                    cout<<"Y"<<endl;
                }
                else
                {
                    cout<<"N"<<endl;
                }
            }
        }
        return 0;
    }
    

    T3 托盘天平

    啊这题我原来的标程写错了,导致数据错了一个点,重新翻看后发现深搜写的有点弱智……现在改对了,还能当题解……

    这题觉得需要简单的讲一下,他需要用到dp和dfs,dfs有两种搜法,搜剩下的和搜去掉的,看看数据范围就能发现搜去掉的显然比搜剩下的不知道快多少……然后就爆搜求出哪些砝码被去掉了,然后是dp,dp的话用sz数组表示这个数有没有出现过,转移方程也不难,那个bl是用来加速的,从之前出现过最大的开始向下搜比从所有可能里最大的往下搜要快。然后……就完了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    long long a[30],bj[30],c[30],sz[4000];
    long long int n,m;
    long long jg=0;
    long long ans=0;
    long long zlzs=0;
    long long bl=0;
    void dp()
    {
        memset(sz,0,sizeof(sz));
        sz[0]=1;
        zlzs=0;
        bl=0;
        for(int i=1;i<=n;i++)
        {
            if(bj[i]==0) 
            {
                for(int j=bl;j>=0;j--)
                {
                    if(sz[j]==1&&sz[j+a[i]]==0)
                    {
                        sz[j+a[i]]=1;
                        zlzs++; 
                    }
                }
                bl+=a[i];
            }
        }
        jg=max(jg,zlzs);
    }
    void dfs(long long wz,long long shu)
    {
        if(shu>m)return;
        if(wz==n+1)
        {
            if(shu==m)dp();
            return; 
        }
        dfs(wz+1,shu);
        bj[wz]=1;
        dfs(wz+1,shu+1);
        bj[wz]=0;
        return;
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        dfs(1,0);
        printf("%lld
    ",jg);
        return 0;
    } 

    T4 购物

    啊这个题看看数据范围,n<=16我觉得会有一种感觉,这题不是深搜就是状压,这题是状压。

    前缀和记录一下前i个商品的价格之和,便于查找,然后转移,转移的过程中求某个硬币可以买多少个商品是要用二分,要不然(在原题中)会超时。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long a[30],dp[100005],sz[100005],qzh[100005],zd=-99999999;
    long long k,n,ans;
    long long jg=0;
    void cl(int shu)
    {
    	ans=0;
    	for(int i=0;i<=k-1;i++)
    	{
    		if((shu>>i)%2==0)
    		{
    			ans+=a[i];
    		}
    	}
    	zd=max(zd,ans);
    }
    long long hs(long long zq,long long wz)
    {
    	long long xwz=-1,l=wz+1,r=n-1;
    	while(l<=r)
    	{
    		long long mid=(l+r)/2;
    		if(qzh[mid]-qzh[wz]<=a[zq])
    		{
    			xwz=mid;
    			l=mid+1;
    		}else
    		{
    			r=mid-1;
    		}
    	}
    	return xwz;
    }
    int main()
    {
    	scanf("%lld%lld",&k,&n);
    	for(int i=0;i<k;i++)
    	{
    		scanf("%lld",&a[i]);
    	}
    	for(int i=0;i<n;i++)
    	{
    		scanf("%lld",&sz[i]);
    		qzh[i]=qzh[i-1]+sz[i];
    	}
    	memset(dp,-1,sizeof(dp));
    	sort(a,a+k);
    	for(int i=0;i<(1<<k);i++)
    	{
    		for(int j=0;j<k;j++)
    		{
    			if((i>>j)%2==1)
    			{
    				dp[i]=max(dp[i],hs(j,dp[i-(1<<j)]));
    			}
    		}
    	}
    	for(int i=0;i<(1<<k);i++)
    	{
    		if(dp[i]==n-1)
    		{
    			cl(i);
    		}
    	}
    	if(zd!=-99999999)
    	{
    		cout<<zd<<endl;
    	}else
    	{
    		cout<<-1<<endl;
    	}
    	return 0;
    }
    

    为我第三题zz的标程道歉

  • 相关阅读:
    POJ 3616 Milking Time(简单DP)
    POJ 2954 Triangle(计算几何Pick定理)
    POJ 3664 Election Time(简单的快速排序)
    POJ 2007 Scrambled Polygon(计算几何凸包)
    POJ 3673 Cow Multiplication(简单数学)
    POJ 3663 Costume Party (快速排序)
    计算几何模板(一)
    [转]Silverlight中使用MVVM(3)
    Silverlight中使用MVVM(2)
    Silverlight使用Binding动态绑定数据
  • 原文地址:https://www.cnblogs.com/lichangjian/p/14336636.html
Copyright © 2020-2023  润新知