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

24ICPC昆明站补题

原题链接
题解参考 1 2

J Just another Sorting Problem 博弈

题意:给定一个长度为n的排列,Alice 的目标是将排列排序,Bob的目标是阻止Alice在有限步内
排序。Alice 可以交换任意两个位置的数字,Bob只能交换相邻两个位置的数字。AB每次都必须操作。

  • A赢:
    • 只有一对逆序,且A先操作
    • n=2 无论AB谁先
    • n=3 123都不在位置上,B先操作,A赢
void solve()
{int n;cin>>n;string s;cin>>s;vector<int>a(n+1);forr(i,1,n)cin>>a[i];//一开始犯蠢想用单调栈求逆序对数...int cnt=0;forr(i,1,n){cnt+=(a[i]!=i);//因为是排列 所以统计不等于下标的数目}if(cnt==0)return cout<<"Alice"<<endl,void();if(cnt==2&&s[0]=='A')return cout<<"Alice"<<endl,void();//手玩发现的特例if(n==2)return cout<<"Alice"<<endl,void();if(n==3){if(s[0]=='B'&&cnt==3){//3 1 2   2 3 1return cout<<"Alice"<<endl,void();}}cout<<"Bob"<<endl;
}

M Matrix Construction 构造

题意:构造一个n×m的矩阵,使得任意“相邻两个位置的数字的和”都互不相等。
没想出来…
看题解是从小到大填充副对角线

  • 一个数的相邻位置数字属于另一条副对角线,所有的和从左上到右下递增,能保证不同对角线上的和两两不同
  • 相同对角线上,从右上到左下递增,也满足和两两不同
const int N = 4e3+10, C = 1e6 + 10, mod =998244353, inf = 1e9 + 10;
int a[N][N];
void solve()
{int n,m;cin>>n>>m;cout<<"yes"<<endl;int cnt=1;forr(i,1,n+m-1){int x=max(1ll,i-m+1),y=min(m,i);// cout<<x<<' '<<y<<endl;while (x<=n&&y>=1){a[x][y]=cnt++;x++,y--;}}forr(i,1,n){forr(j,1,m)cout<<a[i][j]<<' ';cout<<endl;}
}

H Horizon Scanning 滑窗 角度

const double pi=acos(-1);
struct pos
{double x,y;
};void solve()
{int n,k;cin>>n>>k;vector<pos>a(n+1);vector<double>rad(2*n+1);int id=0;forr(i,1,n){cin>>a[i].x>>a[i].y;if(a[i].x>0)rad[++id]=atan(a[i].y/a[i].x)+(a[i].y<0)*2*pi;//一四else if(a[i].x==0){if(a[i].y==0)k--;//(0,0)无论何时都有这个点else rad[++id]=a[i].y/abs(a[i].y)*pi/2;}else rad[++id]=pi+atan(a[i].y/a[i].x);//二三}sort(rad.begin()+1,rad.begin()+id+1);forr(i,1,id){rad[id+i]=rad[i]+2*pi;//绕圈}double ans=0;forr(r,k+1,id+k){int l=r-k;ans=max(rad[r]-rad[l],ans);}cout<<fixed<<setprecision(10)<<ans<<endl;
}

G GCD BFS

题意:给定两个正整数a和b,每次可以选一个数并减去gcd(a,b)。问:至少要多少次操作,才能使a和b都变成0?

  • (0,b)→(0,0)(0,b)\rightarrow (0,0)(0,b)(0,0)一步到位
  • a较小,先把a变成0,就考虑gcd(a,b)会是什么值
    • 考虑二进制,若a&1,b&1都是0,那么gcd(a,b)≥2gcd(a,b)\geq 2gcd(a,b)2
    • 若有一个是1,那么gcd(a,b)&1=1gcd(a,b)\&1=1gcd(a,b)&1=1,减去gcd(a,b)会把最低位1去掉,下一次继续gcd(a,b)≥2gcd(a,b)\geq 2gcd(a,b)2
    • 所以每次对a会去掉2,最后(a,b)→(0,b)(a,b)\rightarrow (0,b)(a,b)(0,b)步数不会太多
struct st{int a,b,stp;
};void solve()
{int a,b;cin>>a>>b;queue<st>q;q.push({a,b,0});while (q.size()){auto [na,nb,stp]=q.front();q.pop();if(na==0||nb==0){cout<<stp+1<<endl;break;}int g=__gcd(na,nb);q.push({na-g,nb,stp+1});q.push({na,nb-g,stp+1});}}

L Last Chance: Threads of Despair 贪心 策略

题意:敌我双方分别有n和m个单位,我方每个单位可以攻击一次,攻击一个敌方单位会使战斗双
方分别-1 生命值,当一个单位生命值清零后会发生一次爆炸,使所有单位生命值-1,询问是否
存在一种攻击方案消灭所有敌方单位。

void solve()
{int n,m;cin>>n>>m;vector<int>a(n+1),b(m+1);forr(i,1,n)cin>>a[i];forr(i,1,m)cin>>b[i];sort(a.begin()+1,a.end());sort(b.begin()+1,b.end());//爆炸伤害>=单次攻击伤害 贪心尽量使用爆炸int atk=0;//攻击次数forr(i,1,n){atk+=a[i]>1;//,所有生命值超过1的我方单位都拥有一次攻击机会}atk+=a[1]==1;//生命值等于1的我方单位加起来总共拥有一次攻击机会int j=1,i=1,bom=0;//从小到大消耗 看能引发多少连锁爆炸 影响后面血量较大的人while (j<=m){while (i<=n||j<=m){//思路:找a[i]中能引发的爆炸会带走多少b中的敌人//先找a[i]中能爆炸的if(i<=n&&a[i]-1<=bom){//更新可爆炸的数量 a[i]-1 因为要用在攻击反伤1滴血i++;bom++;//连锁爆炸数量}else if(j<=m&&b[j]<=bom){//如果当前a[i]凑的连锁爆炸能带走b[j]j++,bom++;//连锁爆炸}else break;//再也没有连锁爆炸}//连锁爆炸推进不下去 用攻击推进爆炸if(j<=m){if(atk>=b[j]-bom){atk-=(b[j]-bom);j++;bom++;}else break;//推进不下去}}if(j>m)ryes;else rno;
}

C Coin 分治 二分 逆推

void solve()
{int n,k;cin>>n>>k;if(k>=n)return cout<<n<<endl,void();auto cal=[&](int x)->int{//计算x长度 多少轮能全部消除int sm=0;while(x){int cnt=(x+k-1)/k;//删去多少个数// int ed=1+(cnt-1)*k;//最后一个数位置s// int d=(x-ed+cnt)/cnt;//删除cnt轮数 ed后面可能有重复删除cnt的操作int ed=(cnt-1)*k;//最后一个数位置sint d=(x-ed+cnt-1)/cnt;//删除cnt轮数 ed后面可能有重复删除cnt的操作x-=d*cnt;sm+=d;//轮数}return sm;};// forr(i,1,n){//   cout<<i<<':'<<cal(i)<<' ';// }cout<<endl;/*20 4
1:1 2:2 3:3 4:4 5:4 6:5 7:5 8:6 9:6 10:6 11:7 12:7 13:7 14:7 15:8 16:8 17:8 18:8 19:8 20:9  第一个cal(x-1)<cal(x)的x会留到最后
*/int ncal=cal(n);int ans;if(ncal<=k||ncal-k>=2e6){//极大/极小 一边倒的 可以二分找第一个cal(mid)==ncal//一次操作消除(n+k-1)/k个数 在最后(n+k-1)/k个数中找  差1的int l=n-(n+k-1)/k+1,r=n; while (l<r){int mid=(l+r)>>1;if(cal(mid)==ncal)r=mid;//找第一个 如果相等 r往前推else l=mid+1;//cal(l-1)<ncal}return cout<<l<<endl,void();}//现在倒数k+1轮int pre=k;ncal-=k;//去掉最后一个一个删的过程forr(i,1,ncal){//向更前面的轮找int now=pre+(pre+k-2)/(k-1);pre=now;}ans=pre;cout<<ans<<endl;
}
http://www.dtcms.com/a/474580.html

相关文章:

  • 口碑好的聊城网站建设设计软件网站
  • 五种编程语言比较选择最适合您项目的工具
  • 商城网站开发项目分工公司网页背景图
  • 第六章:并发编程—Go的杀手锏
  • 网站建设内部流程图定制开发网站 推广
  • 衡石科技HENGSHI SENSE 6.0:重塑企业级BI的技术范式
  • 西安便宜网站建设品牌网十大品牌排行榜
  • OpenSIPS call_center 模块测试
  • 深度学习周报(10.6~10.12)
  • 易语言实现多文件选择对话框模块详解
  • 电子商务网站建设与综合实践如何翻译wordpress主题
  • Java基础--集合复习知识点
  • spdlog讲解
  • 怎样用vps做网站超级优化
  • 下载接口返回的数据流格式文件
  • 关于网站建设的合同范本正规太原软件开发公司有哪些
  • Python反射机制通俗详解(新手友好版)
  • 网站开发要源码多少钱wordpress 静态资源加速
  • 【多线程】阻塞等待(Blocking Wait)(以Java为例)
  • 公众号做 视频网站商品行情软件下载
  • Kubernetes环境下Nginx代理Nacos服务请求故障诊断
  • Linux 文件权限详解与实操命令
  • 1Docker镜像与容器,目录挂载和卷映射的选择
  • 06_k8s数据持久化
  • c 教学网站开发网页设计尺寸大小规范
  • 第一章:AI大模型基本原理及API应用——第一小节
  • 购物便宜的网站有哪些vivo即将发布的新手机
  • 超级玛丽demo9
  • 汕头站扩建什么时候完成做单屏网站 高度是多少
  • 【Swift】LeetCode 1. 两数之和