当前位置: 首页 > ai >正文

2025ICPC武汉邀请赛-F

题意如下图

思路:
考虑一种贪心策略,

假设最大的物品体积为2^v,那么我每个背包都至少要有2^v的体积,那么假设有m个背包,我的容量就增加了m*2^v,如果此时最大的物品有k个,那么现在可以支配给后面小物品的体积就就有(m-k)*2^v也就是(m-k)个2^v,但是这个可支配体积难以表示,所以可以逐位考虑,如果在2^v对应的这个位置有a个可以支配给后面物品的体积,那么在2^(v-1)对应的位置就有2*a个可以支配给后面物品的体积,这样逐位计算,可以做到不用计算体积也能把体积分配下去

用一个简单的图示可以表示这种做法

如图1:2^i下面的1的个数对应物品这一位对应物品个数(这个样例k也就是背包数量为4)

此时只能把背包容量从0扩到2^4

图2,'-'表示背包扩容之后可以支配的体积,用了3个,还剩一个可支配的体积,乘2给到下一位

 图三,刚好抵掉2^3这一位

图四:背包容量从2^4扩容到2^4+2^2,多四个2^2的可支配的体积,用了三个剩一个

 图五:乘二

图六:乘二刚好抵掉,所以这个样例答案为2^4+2^2=20

按照这个思路,可以初步实现代码,但是还有一种情况就是2^m级别的体积向下转移到2^(m-1e9),也就是如果可以支配的有剩余,就会不断*2转移到下一位,但是根据数据范围可以发现可能会出现转移1e9次的情况,这种情况可以发现,转移32次以上,可支配的体积已经达到了2*32级别,那么可支配的体积一定容得下剩余的体积,于是提前结束循环得出答案即可

但是要注意,初始的某一位的物品个数如果超过了背包个数k,那么多余部分要除以二向高位转移,确保每一位的物品个数<=k

代码实现:

#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define u1 (u<<1)
#define u2 (u<<1|1)
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=6e6+10,INF=4e18,P=998244353;
int n,m;
int qmi(int a,int b,int P){int res=1;while(b){if(b&1)res=res*a%P;a=a*a%P;b>>=1;}return res;
}
vector<PII>v(N);
void solve()
{map<int,int>mp;cin>>n>>m;_rep(i,1,n){int a,b;cin>>a>>b;mp[b]+=a;}int idx=0;for(auto i:mp){if(i.se>m){int sub=i.se-m;mp[i.fi]-=sub;if(sub&1){sub++;mp[i.fi]--;}mp[i.fi+1]+=sub/2;}if(mp[i.fi]){v[++idx]={i.fi,mp[i.fi]};}}int pre=-1,res=0,fu=0;_pre(i,idx,1){if(pre==-1){res+=qmi(2,v[i].fi,P);fu=m-v[i].se;}else{if(fu&&pre-v[i].fi>40){cout<<res<<'\n';return ;}else{if(fu){for(int j=pre;j>v[i].fi;j--){//2^jfu*=2;if(fu>2*m){cout<<res<<'\n';return ;}}}if(fu>=v[i].se)fu-=v[i].se;else {v[i].se-=fu;//剩res=res+qmi(2,v[i].fi,P);res%=P;fu=m-v[i].se;}}}pre=v[i].fi;}cout<<res<<'\n';return ;
}
signed main()
{IOS;int T=1;cin>>T;while(T--)solve();return 0;
}

http://www.xdnf.cn/news/7622.html

相关文章:

  • 游戏启动DLL文件缺失怎么解决 解决dll问题的方法
  • Vue学习路线
  • leetcode hot100刷题日记——6.和为 K 的子数组
  • 【Axure视频教程】动态地图路线
  • 实现rpc通信机制(待定)
  • R语言空间分析实战:地理加权回归联合主成份与判别分析破解空间异质性难题
  • 封装POD与PinMap文件总结学习-20250516
  • Go 语言简介
  • 操作系统的基础概念
  • 初步认识HarmonyOS NEXT端云一体化开发
  • AbMole| Phorbol 12-myristate 13-acetate(CAS号16561-29-8;目录号M4647)
  • vue+threeJs 生成烟花效果
  • PEFT简介及微调大模型DeepSeek-R1-Distill-Qwen-1.5B
  • 【css知识】flex-grow: 1
  • LibreHardwareMonitor:.Net开发的开源硬件监控项目
  • 中国机加工的市场概况及冷镦技术对于机加工替代的趋势
  • 如何在 Windows 11/10 PC 上擦除外部硬盘驱动
  • 什么叫生成式人工智能?职业技能的范式转移与能力重构
  • HarmonyOS5云服务技术分享--云存储SDK文章整理
  • 2025年 全国青少年信息素养大赛 算法创意挑战赛C++ 初中组 初赛真题
  • 94.LabelGrid 的遍历与属性编辑 Maui例子 C#例子
  • BioID技术:探索蛋白质相互作用的新方法
  • Java 05正则表达式
  • Linux中FTP服务命令使用与NFS服务
  • JavaScript的Button的contentItem属性
  • 企业建私有云,选择K8S方案会怎么样?
  • [洛谷刷题12]
  • COMSOL软件入门
  • 《棒球知识百科》亚冬会有哪些国家参加·棒球1号位
  • 后期:daplink