首页 > 其他分享 >20230429 模拟赛(jnxxhzz)

20230429 模拟赛(jnxxhzz)

时间:2023-05-03 10:33:38浏览次数:55  
标签:head const val int 20230429 lv maxn jnxxhzz 模拟

T1.神奇零食柜

略,oj上交要加快读

T2.防御工事

数据范围:\(1 \le n,m \le 100\)
不难想到是网络流(虽然我没想到……)
这是一个挺基础的网络流
对于每个\(V\),我们将它们连到一个超级源点上
在往它的四个方向分别建边
最后把所有的\(M\)连到一个汇点上
而在建边时注意其实\(E->E\)的边是没有用的,就可以不用建
最后在跑一个最大流求最小割即可

#include <bits/stdc++.h>
using namespace std;
#define int long long 

const int maxn=1e5+10,INF=0x3f3f3f3f;
const int fx[4]={0,1,0,-1};
const int fy[4]={-1,0,1,0};
int n,m,head[maxn],tot=-1,cur[maxn],lv[maxn],st,ed;
char mp[105][105];
struct edge{
  int v,val,nxt;
}e[maxn*2];

void add(int u,int v,int w){
  e[++tot]=(edge){v,w,head[u]};
  head[u]=tot;
  e[++tot]=(edge){u,0,head[v]};
  head[v]=tot;
}

bool bfs(){
  memset(lv,-1,sizeof(lv));
  cur[st]=head[st];
  lv[st]=0;
  queue<int> q;
  q.push(st);
  while(!q.empty()){
  	int nw=q.front();q.pop();
  	for(int i=head[nw];i!=-1;i=e[i].nxt){
  	  int v=e[i].v,val=e[i].val;
	  if(val>0&&lv[v]==-1){
	  	lv[v]=lv[nw]+1;
	  	cur[v]=head[v];
	  	q.push(v);
	  }	
	}
  }
  return lv[ed]!=-1;
}

int dfs(int nw,int flow){
  if(nw==ed) return flow;
  int res=flow;
  for(int i=cur[nw];i!=-1&&res;i=e[i].nxt){
  	cur[nw]=i;
  	int v=e[i].v,val=e[i].val;
  	if(val>0&&lv[v]==lv[nw]+1){
  	  int c=dfs(v,min(val,res));
	  e[i].val-=c;
	  e[i^1].val+=c;
	  res-=c;	
	}
  }
  return flow-res;
}

int dinic(){
  int ans=0;
  while(bfs())
  	ans+=dfs(st,INF);
  return ans;
}

signed main(){
  scanf("%lld%lld",&n,&m);
  memset(head,-1,sizeof(head));
  for(int i=1;i<=n;i++){
  	scanf("\n");
  	for(int j=1;j<=m;j++) scanf("%c",&mp[i][j]);
  }
  st=0,ed=n*m+1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++){
      if(mp[i][j]=='V') add(st,(i-1)*m+j,INF);//注意行列式的计算啊
      if(mp[i][j]=='M') add((i-1)*m+j,ed,INF);
      for(int k=0;k<4;k++){
      	int x=i+fx[k],y=j+fy[k];
      	if(x>=1&&y>=1&&x<=n&&y<=m) add((i-1)*m+j,(x-1)*m+y,1);
	  }
	}
  printf("%lld\n",dinic());
  return 0;
}

T3.异或三角形

这道题和我之前在洛谷上做的那道同名题挺像的
感觉我的思路也挺像的
就顺着那道题想下去就写出来了
虽然挺冗长的,但终究还是A了
可是在oj上交就只有27分,RE,挺离谱的

源代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int maxn=2e5+10;
const ll mod=998244353;
int len=0,a[maxn];
char ch[maxn];
ll dp[maxn][8][8];

//当前枚举到第id位,a,b,c是否满足条件limit,X是否满足flag
//limit _,_,_ a,b,c是否达到上界
//flag _,_,_ aXc>aXb aXc>bXc aXc<aXb+bXc 
ll dfs(int id,int limit,int flag){
  //1.出口
  if(id==0) return flag==7;
  if(dp[id][limit][flag]!=-1) return dp[id][limit][flag];
  //2.能做的事情 
  ll res=0;
  int bounda=((limit>>2)&1)==1 ? a[id] : 1;
  int boundb=((limit>>1)&1)==1 ? a[id] : 1;
  int boundc=((limit)&1)==1 ? a[id] : 1;
  for(int ia=0;ia<=bounda;ia++)
    for(int ib=0;ib<=boundb;ib++)
	  for(int ic=0;ic<=boundc;ic++){
	  	int m=((ia==bounda)<<2)+((ib==boundb)<<1)+(ic==boundc);
	  	if(ib==ic&&ia!=ib){
	  	  res+=dfs(id-1,limit&m,flag|2);res%=mod;
	  	  continue;
		}
		if(ia==ib&&ic!=ia){
		  res+=dfs(id-1,limit&m,flag|4);res%=mod; 
		  continue;
		}
		if(ia==ib&&ia==ic){
		  res+=dfs(id-1,limit&m,flag);res%=mod;
		  continue;
		}
		if(((flag>>2)&1) && ((flag>>1)&1)){
		  res+=dfs(id-1,limit&m,flag|1);res%=mod;
		}
	  } 
  return dp[id][limit][flag]=res%mod;
} 

int main(){
  memset(dp,-1,sizeof(dp));
  scanf("%s",ch);
  len=strlen(ch);
  for(int i=len-1;i>=0;i--) a[len-i]=(int)(ch[i]-'0');
  printf("%lld\n",(dfs(len,7,0)*3)%mod);
  return 0;
}

题解中的做法比我想得更深入一些
我是钦定了大小关系,而题解中并没有
看起来也要简单得多
也就是说当\(a,b,c\)中每一个数字都与另外两个数有一位不同
这样就不用用递归实现了
时间复杂度就会变小

#include <bits/stdc++.h>
using namespace std;
#define ll long long 

const int maxn=2e5+10;
const int f[8]={0,1,2,4,4,2,1,0};
const ll mod=998244353;
int len;
char ch[maxn];
ll dp[maxn][8][8],ans=0; 

int main(){
  scanf("%s",ch);
  len=strlen(ch);
  dp[0][0][0]=1;
  for(int i=0;i<len;i++)
    for(int j=0;j<8;j++)//枚举limit 
      for(int k=0,F=ch[i]&1?7:j;k<8;k++)
        for(int l=0;l<8;l++)//枚举每一位真实的值
		  if((l&F)==l) //没有越界
		    (dp[i+1][j|(l^F)][k|f[l]]+=dp[i][j][k])%=mod; 
  for(int i=0;i<8;i++) (ans+=dp[len][i][7])%=mod;
  printf("%lld\n",ans%mod);
  return 0;
}

总结

  1. 还是要注意时间的把控,再分析问题时还不够深入
  2. 没有必要的循环一定不要加,如T3中char直接可以异或就不用转化成int
  3. 数位dp在能用循环写就不要用记忆化
  4. 对于网络流的题目还不够敏感,看到数据范围较小的图论问题就可以考虑网络流

标签:head,const,val,int,20230429,lv,maxn,jnxxhzz,模拟
From: https://www.cnblogs.com/hewanying0622/p/17367761.html

相关文章

  • 【通信仿真】基于matlab模拟自相干算法仿真
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 亲测可用的NS2对"1. AODV" "2. DSDV" "3. DSR" 的路由模拟
    seta1while{$a==1}{puts"EntertheRoutingAgentsinmobilenetworking"puts"1.AODV"puts"2.DSDV"puts"3.DSR"settop[getsstdin]if{$top==1}{setopt(chan)Channe......
  • 【雷达通信】基于matlab模拟毫米波雷达成像
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 【机械仿真】基于matlab模拟自动摆钟
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 4.29 模拟赛
    A良数先全填1,然后暴力搜索每一位改成什么。可以发现答案中修改的位数都比较少,可以直接dfs。记忆化不需要存各个数字的顺序和次数,只和当前修改的位数和当前的和有关。B良点先拓扑排序只留下环,剩余点中度数最大且编号最小的可能是答案。如果拓扑完没有环或者去掉这个点后......
  • 数组模拟实现数据结构
    数组模拟链表实现①单链表:邻接表(存储图和树)②双链表:优化某些问题单链表inte[N]存储val,intne[N]存储next//单链表模板inthead,e[N],ne[N],idx;//head表示头节点的下标,e[i]表示节点i的值,ne[i]表示节点i的指针是多少,idx存储当前已经用到了哪个点v......
  • 模拟退火算法
    访问【WRITE-BUG数字空间】_[内附完整源码和文档]该项目主要是利用局部搜索算法(LS)和模拟退火算法(SA)解决TSP问题。先是使用LS求解TSP问题,再尝试SA问题,比较两者,在效率上SA更占有。最后再在LS的基础上使用SA,再优化SA部分算法,尝试求解TSP问题。选用的TSP测例为eil1......
  • 【带DC引脚SPI屏】STM32L010K8超低功耗单片机软件模拟SPI驱动ST7567点阵屏12864示例
    显示屏驱动芯片多种多样,有的不带DC,通过接收的数据的某个特定位确定是命令还是数据,比如常见的12864移植案例在【不带DC脚的spi屏】STM32F103C8移植u8g2在软件模拟spi模式下驱动st7920带字库的12864显示屏-不打鱼光晒网-博客园(cnblogs.com)和【不带DC脚的spi屏】stm32f1......
  • STM32单片机软件模拟I2C读取AM2320温湿度传感器数据
    STM32单片机使用软件模拟IIC读取AM2320温湿度传感器的数据并显示在0.96寸OLED屏上。我用的单片机是STM32F103C8T6,程序用的是ST标准库写的。STM32使用硬件I2C读取SHTC3温湿度传感器:https://blog.zeruns.tech/archives/692.htmlSTM32单片机读取AHT10温湿度传感器数据:https://blog.ze......
  • mac 夜神模拟器安装xposed
    1.下载xposed框架链接:https://pan.baidu.com/s/18B-6Byzg3rAQpAkjSYAMAQ?pwd=dzqd提取码:dzqd2.下载解压后cd~/Downloads/xposedadbconnect127.0.0.1:62001adbremountadbpushxposed/systemadbshellsucd/systemmount-oremount-w/system cd xposed......