C. Game with Multiset

原题链接

反思:要把各种可能的情况都判断一遍再提交!不要急着提交

简介

仓库里有若干个二次方数,请问是否能取出若干数使得刚好等于给定数?

情况讨论

情况1.仓库里只有一个4,但是我要求2,求不得
情况2.仓库里有三个1,我要求3,能求

大概思路

i[log2(v),0]遍历(从大到小),如果对于i,仓库里有,就一直减2i直到无法再减(再减就小于零或库里的i次数用光了)

细节注意

1.for循环减法可以用一次性减法(除法找出减的次数)代替,速度会快很多
2.v不会超过109,所以2i也不会超过long long 范围
3.pow函数比较耗时,可以用(1<<n)或者log2代替

代码1

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    ll n;
    cin>>n;
    ll a[35]={0};
    while(n--)
    {
        ll q,v;
        cin>>q>>v;
        if(q==1) a[v]++;
        else
        {
            int i=log2(v);;//1.判断是否正常退出
            //2.代表最外面的1的位置
            for(i;i>=0;i--)//不从29开始,一定程度的优化
            {
                ll b=a[i];//仓库里i的数量
                ll d=pow(2,i);//当前i代表的实际值
                if(log2(v)>=i) v-=min(b,v/d)*d;//最多能减多少乘上减去的值,核心优化
                if(v==0)break;
            }
            if(i!=-1)puts("YES");
            else puts("NO");
        }
    }
    return 0;
}

dalao的代码2

#include<bits/stdc++.h>
using namespace std;
int c[60];
int main(){
	ios::sync_with_stdio(false),cin.tie(0);
	int q,op,v,i,j;
	for(cin>>q;q>0;q--)
	{
		cin>>op;
		if(op==1)
		{
			cin>>v;
			c[v]++;
			for(i=0;i<59;i++)
			{
				if(c[i]==3)//4可以由一个4组成,也可以由两个2组成,任意一个数可以由1 or 0个二次方数组成,多出来的部分就可以去进位Orz
				{
					c[i]-=2;
					c[i+1]++;
				}
			}
		}
		if(op==2)
		{
			cin>>v;
			for(i=30;i>-1;i--)
			{
				for(j=0;j<c[i];j++)
				{
					if(v>=(1<<i))v-=(1<<i);
				}
			}
			if(v==0)cout<<"YES\n";
			else cout<<"NO\n";
		}
	}
	return 0;
}
posted @   纯粹的  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示