首页 > 其他分享 >多校A层冲刺NOIP2024模拟赛21

多校A层冲刺NOIP2024模拟赛21

时间:2024-11-12 21:09:00浏览次数:1  
标签:cnt 21 int make work 多校 pair NOIP2024 dis

多校A层冲刺NOIP2024模拟赛21

\(T1\) A. 送信卒 \(90pts/100pts\)

  • 部分分

    • \(90pts\)

      • 设最后的可能的最短路中左右共移动了 \(d\) 次,上下共移动了 \(x\) 次。

      • 则等价于求 \(\min \{ x_{i}k+d_{i} \}=s\) 的解,观察到 \(d \in [0,\min(\left\lceil \frac{nm}{2} \right\rceil,s)]\) 。

      • 将左右移动次数也扔进 \(Dijkstra\) 中转移即可,然后暴力进行 \(check\) ,时间复杂度为 \(O(n^{4}\log n)\) 。

      • 因为需要 \(O(n^{4})\) 的辅助空间,所以需要开 short

        点击查看代码
        const double eps=1e-8;
        struct node
        {
            int nxt,to,x,d;
        }e[40010];
        int head[10010],cnt=0,n,m,limit;
        short dis[10010][5010];
        bitset<5010>vis[10010];
        char c[110][110];
        struct quality
        {
            short dis;
            int x,d;
            bool operator < (const quality &another) const
            {
                return dis>another.dis;
            }
        };
        void add(int u,int v,int x,int d)
        {
            cnt++;
            e[cnt].nxt=head[u];
            e[cnt].to=v;
            e[cnt].x=x;
            e[cnt].d=d;
            head[u]=cnt;
        }
        int work(int x,int y)
        {
            return (x-1)*m+y;
        }
        void dijkstra(int s)
        {
            memset(dis,0x3f,sizeof(dis));
            priority_queue<quality>q;
            dis[s][0]=0;
            q.push((quality){dis[s][0],s,0});
            while(q.empty()==0)
            {
                int x=q.top().x,d=q.top().d;
                q.pop();
                if(vis[x][d]==0)
                {
                    vis[x][d]=1;
                    for(int i=head[x];i!=0;i=e[i].nxt)
                    {
                        if(d+e[i].d<=limit&&dis[e[i].to][d+e[i].d]>dis[x][d]+e[i].x)
                        {
                            dis[e[i].to][d+e[i].d]=dis[x][d]+e[i].x;
                            q.push((quality){dis[e[i].to][d+e[i].d],e[i].to,d+e[i].d});
                        }
                    }
                }
            }
        }
        int main()
        {
        #define Issac
        #ifdef Issac
            freopen("msg.in","r",stdin);
            freopen("msg.out","w",stdout);
        #endif
            int sx,sy,tx,ty,t,i,j;
            double s,ans=0x7f7f7f7f,k,minn;
            scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty);
            t=work(tx,ty);
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=m;j++)
                {
                    scanf(" %c",&c[i][j]);
                }
            }
            cin>>s;
            limit=min(ceil(n*m/2.0),ceil(s)-1);
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=m;j++)
                {
                    if(c[i][j]=='0')
                    {
                        if(i-1>=0&&c[i-1][j]=='0'){add(work(i,j),work(i-1,j),1,0);}
                        if(i+1<=n&&c[i+1][j]=='0'){add(work(i,j),work(i+1,j),1,0);}
                        if(j-1>=0&&c[i][j-1]=='0'){add(work(i,j),work(i,j-1),0,1);}
                        if(j+1<=m&&c[i][j+1]=='0'){add(work(i,j),work(i,j+1),0,1);}
                    }
                }
            }
            dijkstra(work(sx,sy));
            if((int)s==s&&tx==sx&&abs(ty-sy)==(int)s)
            {
                ans=0;
            }
            else
            {
                for(i=0;i<=limit;i++)
                {
                    if(dis[t][i]!=0x3f3f&&dis[t][i]!=0)
                    {
                        k=1.0*(s-i)/dis[t][i];
                        minn=0x7f7f7f7f;
                        for(j=0;j<=limit;j++)
                        {
                            if(minn-(1.0*j+1.0*k*dis[t][j])>eps)
                            {
                                minn=1.0*j+1.0*k*dis[t][j];
                            }
                        }
                        if(fabs(minn-s)<=eps&&ans-k>eps)
                        {
                            ans=k;
                        }
                    }
                }
            }
            printf("%.3lf\n",ans);
            return 0;
        }
        
    • \(100pts\) :将上述做法的 \(dijsktra\) 改成 \(01BFS\) 即可,时间复杂度为 \(O(n^{4})\) 。

      点击查看代码
      const double eps=1e-8;
      struct node
      {
          int nxt,to,x,d;
      }e[40010];
      int head[10010],cnt=0,n,m,limit;
      short dis[10010][5010];
      bitset<5010>vis[10010];
      char c[110][110];
      void add(int u,int v,int x,int d)
      {
          cnt++;
          e[cnt].nxt=head[u];
          e[cnt].to=v;
          e[cnt].x=x;
          e[cnt].d=d;
          head[u]=cnt;
      }
      int work(int x,int y)
      {
          return (x-1)*m+y;
      }
      void bfs(int s)
      {
          memset(dis,0x3f,sizeof(dis));
          deque<pair<int,int> >q;
          dis[s][0]=0;
          q.push_back(make_pair(s,0));
          while(q.empty()==0)
          {
              int x=q.front().first,d=q.front().second;
              q.pop_front();
              if(vis[x][d]==0)
              {
                  vis[x][d]=1;
                  for(int i=head[x];i!=0;i=e[i].nxt)
                  {
                      if(d+e[i].d<=limit&&dis[e[i].to][d+e[i].d]>dis[x][d]+e[i].x)
                      {
                          dis[e[i].to][d+e[i].d]=dis[x][d]+e[i].x;
                          if(e[i].x==1)
                          {
                              q.push_back(make_pair(e[i].to,d+e[i].d));
                          }	
                          else
                          {
                              q.push_front(make_pair(e[i].to,d+e[i].d));
                          }
                      }
                  }
              }
          }
      }
      int main()
      {
      #define Issac
      #ifdef Issac
          freopen("msg.in","r",stdin);
          freopen("msg.out","w",stdout);
      #endif
          int sx,sy,tx,ty,t,i,j;
          double s,ans=0x7f7f7f7f,k,minn;
          scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty);
          t=work(tx,ty);
          for(i=1;i<=n;i++)
          {
              for(j=1;j<=m;j++)
              {
                  scanf(" %c",&c[i][j]);
              }
          }
          cin>>s;
          limit=min(ceil(n*m/2.0),ceil(s)-1);
          for(i=1;i<=n;i++)
          {
              for(j=1;j<=m;j++)
              {
                  if(c[i][j]=='0')
                  {
                      if(i-1>=0&&c[i-1][j]=='0'){add(work(i,j),work(i-1,j),1,0);}
                      if(i+1<=n&&c[i+1][j]=='0'){add(work(i,j),work(i+1,j),1,0);}
                      if(j-1>=0&&c[i][j-1]=='0'){add(work(i,j),work(i,j-1),0,1);}
                      if(j+1<=m&&c[i][j+1]=='0'){add(work(i,j),work(i,j+1),0,1);}
                  }
              }
          }
          bfs(work(sx,sy));
          if((int)s==s&&tx==sx&&abs(ty-sy)==(int)s)
          {
              ans=0;
          }
          else
          {
              for(i=0;i<=limit;i++)
              {
                  if(dis[t][i]!=0x3f3f&&dis[t][i]!=0)
                  {
                      k=1.0*(s-i)/dis[t][i];
                      minn=0x7f7f7f7f;
                      for(j=0;j<=limit;j++)
                      {
                          if(minn-(1.0*j+1.0*k*dis[t][j])>eps)
                          {
                              minn=1.0*j+1.0*k*dis[t][j];
                          }
                      }
                      if(fabs(minn-s)<=eps&&ans-k>eps)
                      {
                          ans=k;
                      }
                  }
              }
          }
          printf("%.3lf\n",ans);
          return 0;
      }
      
  • 正解

    • 观察到 \(\min \{ x_{i}k+d_{i} \}\) 具有单调性,即随着 \(k\) 的增大最短路长度不降。
    • 二分答案即可。
    点击查看代码
    const double eps=1e-8;
    double dis[110][110];
    bool vis[110][110];
    char c[110][110];
    void dijkstra(int sx,int sy,double mid,int n,int m)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                vis[i][j]=0;
                dis[i][j]=0x3f3f3f3f;
            }
        }
        priority_queue<pair<int,pair<int,int>>>q;
        dis[sx][sy]=0;
        q.push(make_pair(-dis[sx][sy],make_pair(sx,sy)));
        while(q.empty()==0)
        {
            int x=q.top().second.first,y=q.top().second.second;
            q.pop();
            if(vis[x][y]==0)
            {
                vis[x][y]=1;
                if(x-1>=1&&dis[x-1][y]>dis[x][y]+mid&&c[x-1][y]=='0')
                {
                    dis[x-1][y]=dis[x][y]+mid;
                    q.push(make_pair(-dis[x-1][y],make_pair(x-1,y)));
                }
                if(x+1<=n&&dis[x+1][y]>dis[x][y]+mid&&c[x+1][y]=='0')
                {
                    dis[x+1][y]=dis[x][y]+mid;
                    q.push(make_pair(-dis[x+1][y],make_pair(x+1,y)));
                }
                if(y-1>=1&&dis[x][y-1]>dis[x][y]+1&&c[x][y-1]=='0')
                {
                    dis[x][y-1]=dis[x][y]+1;
                    q.push(make_pair(-dis[x][y-1],make_pair(x,y-1)));
                }
                if(y+1<=m&&dis[x][y+1]>dis[x][y]+1&&c[x][y+1]=='0')
                {
                    dis[x][y+1]=dis[x][y]+1;
                    q.push(make_pair(-dis[x][y+1],make_pair(x,y+1)));
                }
            }
        }
    }
    int main()
    {
    #define Issac
    #ifdef Issac
        freopen("msg.in","r",stdin);
        freopen("msg.out","w",stdout);
    #endif
        int n,m,sx,sy,tx,ty,i,j;
        double s,l=0,r,mid,ans=-1;
        cin>>n>>m>>sx>>sy>>tx>>ty;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                cin>>c[i][j];
            }
        }
        cin>>s;
        r=s;
        while(r-l>=eps)
        {
            mid=(l+r)/2;
            dijkstra(sx,sy,mid,n,m);
            if(dis[tx][ty]>=s)
            {
                ans=mid;
                r=mid;
            }
            else
            {
                l=mid;
            }
        }
        printf("%.3lf\n",ans);
        return 0;
    }
    

\(T2\) B. 共轭树图 \(0pts/0pts\)

  • 不妨钦定 \(u>v\) ,那么在断开 \((u,v)\) 这条边后等价于将 \(u\) 的深度最浅的祖先和 \(v\) 连接。故最终得到的 \(G\) 也一定是棵树,且当以 \(n\) 为根时也满足父亲节点的编号一定大于自身的编号。

  • 考虑这样的 \(G\) 是怎么构造出来的。当把 \(G\) 的边在原图上画出后,任意两条边之间只能不交和包含,因为如果相交的话下边的那条边的端点就可以连到上面的边上去。

  • 定义根节点的深度为 \(1\) 。

  • 设 \(f_{x,i}\) 表示 \(x\) 在 \(G\) 中只被允许与原图中它的 \(i \in [1,dep_{x}-1]\) 个祖先连边时(即 \(G\) 中的父亲节点)以 \(x\) 为根的子树中的方案数,状态转移方程为 \(f_{x,i}=\sum\limits_{j=2}^{i+1}\prod\limits_{y \in Son(x)}f_{y,j}\) ,边界为 \(f_{x,i}=i(i \in [1,dep_{x}-1] \land du_{x}=1)\) 。

  • 此时时间复杂度为 \(O(n^{3})\) ,考虑进一步优化。

  • 手摸展开后的式子,容易有 \(f_{x,i}=f_{x,i-1}+\prod\limits_{y \in Son(x)}f_{y,i+1}\) 。此时时间复杂度就优化成了 \(O(n^{2})\) 。

  • 最终,有 \(\prod\limits_{x \in Son(n)}f_{x,1}\) 即为所求。

    点击查看代码
    const ll p=998244353;
    int dep[3010],f[3010][3010];
    vector<int>e[3010];
    void add(int u,int v)
    {
        e[u].push_back(v);
    }
    void dfs(int x,int fa)
    {
        dep[x]=dep[fa]+1;
        for(int i=0;i<e[x].size();i++)
        {
            dfs(e[x][i],x);
        }
        for(int k=1;k<=dep[x]-1;k++)
        {
            f[x][k]=1;
            for(int i=0;i<e[x].size();i++)
            {
                f[x][k]=1ll*f[x][k]*f[e[x][i]][k+1]%p;
            }
            f[x][k]=(f[x][k]+f[x][k-1])%p;
        }
    }
    int main()
    {
    #define Issac
    #ifdef Issac
        freopen("reflection.in","r",stdin);
        freopen("reflection.out","w",stdout);
    #endif
        int n,u,v,ans=1,i;
        cin>>n;
        for(i=1;i<=n-1;i++)
        {
            cin>>u>>v;
            if(u<v)
            {
                swap(u,v);
            }
            add(u,v);
        }
        dfs(n,0);
        for(i=0;i<e[n].size();i++) 
        {
            ans=1ll*ans*f[e[n][i]][1]%p;
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(T3\) C. 摸鱼军训 \(0pts/0pts\)

  • 部分分
    • \(20 \%\) : \(O(n^{2})\) 预处理 \(O(1)\) 查询。

\(T4\) D. 神奇园艺师 \(0pts/0pts\)

  • 部分分
    • 子任务 \(1\) :爆搜子集后就是货仓选址问题了,暴力分解质因数即可。

总结

  • \(T1\) 赛时觉得因为 \(k\) 的变化会导致最短路路径的变化然后就不能确定最短路长度了,没搞清其内部的单调性。
  • \(T2\) 始终没读懂题意。
  • \(T3\) 忘了可以 \(O(n^{2})\) 预处理,最低档部分分只写了单组询问 \(O(n^{2})\) 的做法,挂了 \(20pts\) 。
  • \(T4\) 质因数分解写的是预处理素数挨个分解的方法,导致无用素数极多,挂了 \(20pts\) 。

标签:cnt,21,int,make,work,多校,pair,NOIP2024,dis
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18542646

相关文章

  • 打卡信奥刷题(221)用C++信奥P1740[普及组/提高] Diamond A&B(1)
    DiamondA&B(1)题目背景由于本题较难,将本题拆做两题,分别为diamondA以及diamondB。本题为DiamondA。题目描述教主上电视了!这个消息绝对是一个爆炸性的新闻。一经传开,大街上瞬间就没人了(都回家看电视去了),商店打烊,工厂停业。大家都把电视机的音量开到最大,教主的声音......
  • 21天教你学会PCIe专栏(5)--事务层(Transaction Layer)
    目录第5天:事务层(TransactionLayer)课程目标课程内容1.事务层概述2.事务类型3.请求和响应机制4.事务层的配置和管理5.实际应用示例课后练习结语第5天:事务层(TransactionLayer)课程目标理解PCIe事务层的基本概念和功能掌握事务类型及其工作原理了解请求和响应......
  • HDU - 4821 String
    给定字符串\(S\)。求有多少长\(M\timesL\)的子串,使得将其划分成\(M\)个长度为\(L\)的字符串\(S_1,S_2,\dotsS_M\)互不相同。\(1\leM\timesL\le|S|\le10^5\)。从\(0\)起下标。显然这些字符串的起始位置在模\(L\)意义下相同。不妨枚举这个值\(r\in[......
  • NOIP2024模拟赛#18 总结
    头要炸了。T1题面很好懂,手玩了一下发现答案最小是\((m-1)\timesn\)。可能会多出来一个长度为\(k\)的部分,会发现如果多出来一个长度为\(k\)的部分且合法,那么单个串\(1\simk\)位与\(n-k+1\simn\)位一定相同,\(k+1\simn\)位与\(1\simn-k\)一定相同。Hash判一下即......
  • 『模拟赛』NOIP2024加赛4
    Rank给我唐完了,又名,【MX-S5】梦熊NOIP2024模拟赛1。A.王国边缘好像简单倍增就做完了。由于昨天T5在我脑海中留下了挥之不去的印象,今天一上来看到这题就发现是一个内向基环树森林。然后被硬控硬控硬控,最后一个小点加一点优化就能过没调出来,挂30pts,菜菜菜菜菜。注......
  • comp9021 olygons Python
    Assignment2,Trimester3,2024Generalmatter1.1.Aims.Thepurposeoftheassignmentisto:designandimplementaninterfacebasedonthedesiredbehaviourofanapplicationprogram;practicetheuseofPythonsyntax;developproblemsolvingsk......
  • CVE-2021-21311
    CVE-2021-21311今天要记录的是ssrf,cve编号为CVE-2021-21311Adminer是一个PHP编写的开源数据库管理工具,支持MySQL、MariaDB、PostgreSQL、SQLite、MSSQL、Oracle、Elasticsearch、MongoDB等数据库。在其4.0.0到4.7.9版本之间,连接ElasticSearch和ClickHouse数据库时存在一处......
  • 代码随想录算法训练营第二十二天| leetcode77. 组合、leetcode216.组合总和III、leetc
    1leetcode77.组合题目链接:77.组合-力扣(LeetCode)文章链接:代码随想录视频链接:带你学透回溯算法-组合问题(对应力扣题目:77.组合)|回溯法精讲!_哔哩哔哩_bilibili思路:开始想循环,感觉行不通,然后看了视频,就嗯理解了一些感觉跟递归的思路确实差不多1.1回溯三部曲回溯的方法首......
  • NOIP2024加赛4
    简评:搬的梦熊的,一签一难两不可做。王国边缘倍增板子(但我不会打倍增所以场上调了半天)。记\(f_{i,j}\)表示从\(i\)开始走\(2^j\)次时走的距离,\(g_{i,j}\)表示从\(i\)开始走\(2^j\)次时走到的点,这个用倍增。处理\(f_{i,0}\)和\(g_{i,0}\)时分讨即可,卡不卡常无所谓。时空复杂度\(O......
  • 第21节 arkts 如何读取普通文件
    在ArkTS中读取普通文件可以通过以下几种方式:使用@ohos.fileio模块@ohos.fileio模块提供了一系列用于文件操作的接口,可以用于读取普通文件。以下是一个简单的示例,展示如何读取一个文本文件的内容:importfileiofrom'@ohos.fileio';@Entry@Componentstruct......