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

23ICPC沈阳站补题

思路来源

E dp BFS记忆化搜索

羊过河
记录羊和狼的数量状态
注意queue中的操作步数是递增的,每个状态第一次遍历到一定是最小的步数

const int N=105,mod=1e9+7,inf=1e9+10;
int x,y,p,q;
int dp[N][N][2];//[sheep数量][wolf数量][0:本岸到对岸 1:从对岸回来]
struct st{int s,w,dir;
};
//记忆化搜索
void solve(){cin>>x>>y>>p>>q;// memset(dp,0x3f,sizeof dp);// if(y>x+2*q)return cout<<-1<<endl,void(); 可以一些动物在船上 所以该条件不能判断非法dp[x][y][0]=0;//[w][s]只记录0岸边的queue<st>qu;//注意先到的步数最少 qu的dir递增qu.push({x,y,0});int ans=inf;while(qu.size()){auto [s,w,dir]=qu.front();qu.pop();// if(s==0)ans=min(ans,dp[s][w][dir]);在前面的一定步数很少if(s==0)return cout<<dp[s][w][dir]<<endl,void();if(dir==0){//枚举运走多少forr(i,0,min(p,s)){forr(j,0,min(p-i,w)){if(s>i&&w-j>s-i+q)continue;//此岸不会有伤亡if(dp[s-i][w-j][dir^1]==0){//最先到的一定是步数最少的qu.push({s-i,w-j,dir^1});dp[s-i][w-j][dir^1]=dp[s][w][dir]+1;}//TLE:多次更新// if(dp[s-i][w-j][dir^1]>=dp[s][w][dir]+1){//     qu.push({s-i,w-j,dir^1});//     dp[s-i][w-j][dir^1]=dp[s][w][dir]+1;// }}}}else {//对岸运来多少forr(i,0,min(p,x-s)){forr(j,0,min(p-i,y-w)){if(x-s>i&&y-w-j>x-s-i+q)continue;//对岸没有伤亡// if(dp[s+i][w+j][dir^1]>=dp[s][w][dir]+1){//     qu.push({s+i,w+j,dir^1});//     dp[s+i][w+j][dir^1]=dp[s][w][dir]+1;// }if(dp[s+i][w+j][dir^1]==0){qu.push({s+i,w+j,dir^1});dp[s+i][w+j][dir^1]=dp[s][w][dir]+1;}}}}}cout<<-1<<endl;
}

J 思维

一开始没理解好“isomorphic(同构)”的意思,不是点的标号对应,而是结构对应
u,v两个值中若有叶子节点,变过去就同构。
每次选非叶子节点,把它变成叶子节点。

int deg[N];
//每次操作都会多一个叶子节点
//注意理解“同构” 不是“相同”
void solve(){int n;cin>>n;forr(i,1,n-1){int u,v;cin>>u>>v;deg[u]++,deg[v]++;}int cnt=0;forr(i,1,n){if(deg[i]>1)cnt++;}if(cnt>0&&(cnt-1)&1)cout<<"Alice"<<endl;else cout<<"Bob"<<endl;
}

K 线段树动态开点

给出变化值,求max rating可能的层数区间,初始max rating是0,正数顺序摆放可以创造贡献

  • 最多的层数:正数顺序放在开始,后面掉分无贡献
  • 最少的:负数放在开始,让一部分正数去抵消。贪心思想:用较小的正数,抵消的层数多,把较大的正数放在后面。
const int N=1e6+5,mod=1e9+7,inf=1e9+10;
int a[N],id;
//线段树 对sum区间修改单点访问 
//和值动态开点 对区间二分 贪心
struct node{int lt,rt;//子节点值int l,r;//维护的数值范围int sum,cnt;//和值 区间数字个数
}tr[N*10];
void pushup(int pos){tr[pos].sum=tr[tr[pos].lt].sum+tr[tr[pos].rt].sum;tr[pos].cnt=tr[tr[pos].lt].cnt+tr[tr[pos].rt].cnt;
}
void add(int &pos,int l,int r,int val,int op){if(!pos){//新节点pos=++id;tr[pos].l=l,tr[pos].r=r;}if(l==r){tr[pos].sum+=val*op;tr[pos].cnt+=op;return;}int mid=(l+r)>>1;if(val<=mid)add(tr[pos].lt,l,mid,val,op);else add(tr[pos].rt,mid+1,r,val,op);pushup(pos);
}
//最少用多少
//输入的sum是先负再正的总值
int query(int pos,int l,int r,int sum){if(sum<=0)return 0;if(l==r){//sum已经除掉>l部分,sum中包含tr[pos].cnt个l值return (sum+l-1)/l;//这里就计算多少个l值能把sum搞到<0}int mid=(l+r)>>1;//算后面正数 抵消前面负数后剩的贡献if(tr[tr[pos].rt].sum>=sum)return query(tr[pos].rt,mid+1,r,sum);else return query(tr[pos].lt,l,mid,sum-tr[tr[pos].rt].sum)+tr[tr[pos].rt].cnt;//让前面小的去抵消负数
}
void solve(){int n,q;cin>>n>>q;int sm=0,rt=0;forr(i,1,n){cin>>a[i];if(a[i]>0)add(rt,1,inf,a[i],1);//把正数记录下来sm+=a[i];}forr(i,1,q){int x,v;cin>>x>>v;if(a[x]>0)add(rt,1,inf,a[x],-1);if(v>0)add(rt,1,inf,v,1);sm+=v-a[x];a[x]=v;cout<<tr[1].cnt-query(1,1,inf,sm)+1<<endl;}
}

M 找规律 进制

需要灵机一动
s→ts\rightarrow tsts⊕s=0→s⊕ts\oplus s=0\rightarrow s\oplus tss=0st
而要经过t点k次,就要0→00\rightarrow 000
发现按题意转移,每两位按00→01→11→1000\rightarrow01\rightarrow11\rightarrow1000011110变化,可以看作四进制

const int N=1e6+2,V=2e4+5,mod=1e9+7,inf=1e9+10;
int p[N+5];int qpos(int x,int p=mod-2){int res=1;for(;p;p>>=1,x=1ll*x*x%mod)if(p&1)res=res*x%mod;return res;
}
void init(){p[0]=1;forr(i,1,N)p[i]=p[i-1]*4%mod;forr(i,1,N)(p[i]+=p[i-1])%mod;
}
void solve(){string s,t;cin>>s>>t;int k;cin>>k;int ls=s.size(),lt=t.size();s=' '+s,t=' '+t;//发现规律 00->01->11->10 四进制//以进制思维去想//0->s^t + 0->0//s^treverse(s.begin()+1,s.end());reverse(t.begin()+1,t.end()); if(ls<=lt){forr(i,ls+1,lt)s+='0';ls=lt;}else {forr(i,lt+1,ls)t+='0';}forr(i,1,ls)s[i]=(s[i]!=t[i])+'0';//0->0//判断合法:后面的00有多少个 k就能循环多少圈 即z/2 +1是初始状态int z=0;forr(i,1,ls){if(s[i]=='1')break;else z++;}if(ls!=z&&z/2+1<k)return cout<<-1<<endl,void();//0->s^tif(ls&1)s+='0';int ans=0;for(int i=1;i<=ls;i+=2){//p是4^0+...+4^pos 就是本位四进制转多少圈回0 //从低到高位去掉1if(s[i]=='0'&&s[i+1]=='1')(ans+=3*p[i/2]%mod)%=mod;//10 要转3圈 00->01->11->10else if(s[i]=='1'&&s[i+1]=='1')(ans+=2*p[i/2]%mod)%=mod;//11 转2圈00->01->11else if(s[i]=='1'&&s[i+1]=='0')(ans+=p[i/2])%=mod;//01 转一圈00->01} // cout<<ans<<endl;(ans+=(qpos(4,k)-4+mod)%mod*qpos(3)%mod)%=mod;cout<<ans<<endl;
}
http://www.dtcms.com/a/431059.html

相关文章:

  • C++编程陷阱:悬空引用检测方法与防范指南
  • 上海网站制作价格又拍云存储WordPress
  • 阿里开源 Java 诊断神器Arthas
  • 网页设计与网站建设课程设计报告哪里有市场营销培训班
  • Spring Security入门指南:为初学者打造的安全防护盾
  • 网站策划书模板装修公司怎么做免费网站
  • numpy矩阵运算
  • 让 Agent 说“机器能懂的话”——LlamaIndex 构建 Agent 的结构化输出策略
  • 网站建设栏目怎么介绍海南万宁市
  • 2009 年真题配套词汇单词笔记(考研真相)
  • 代充网站怎么做wordpress4.8.2
  • GundamSeed001
  • ESP32 IDF GET_HTTPS
  • 算法世界中的两极对话:最小化最大差值与最大化数字差异的智慧较量
  • 【含文档+PPT+源码】基于微信小程序的关爱老年人在线能力评估系统
  • 前端-JavaScript简介JavaScript模块化
  • 建设官方网站房产信息网的官网链接
  • ◆comfyUI教程◆第1章05节 详解基础工作流节点及参数功能
  • 华为铁三角:销服体系的变革方法论
  • 【数据库知识】TxSQL 主从数据库同步底层原理深度解析
  • 17zwd一起做网站百度地图怎么看沿途服务区
  • 语义场理论中的5个关键概念
  • 如何自己建立网站前端自己做博客网站
  • 812. 最大三角形面积
  • 【开题答辩全过程】以 springboot药店同城配送系统为例,包含答辩的问题和答案
  • 淘小说APP(免费阅读海量小说)
  • 自动化测试系列之pytest<一>
  • 上海自建站招聘网络营销的含义和特点
  • 闵行建设机械网站游戏开发指南
  • 30.响应式联系信息板块,采用 HTML 和 CSS | CSS 新形态设计