NOIP2024模拟3:一路破冰

雨后的青山。——240316

A-无向图删边

  • 一句话题面:规定一轮中的删边方式为:按边权递减且每轮删掉的边集中没有环。问每条边会在第几轮被删除。

  • 暴力的想法就是跑 \(k\) 轮最大生成树。

  • 优化分两步:

  • 1、主客转化:暴力是求每一轮中会删那些边,以轮数为主体;现在我们考虑每条边会在那一轮被删除,即以点为主体。进一步的来讲,在保证边权递减的删除方式下,一条边最早会在哪一轮不连通。

  • 2、玄学优化:\(n\) 很小,因此会有很多权值不同的重边,记 \(las[x][y]\) 表示 \((x,y)\) 之间的上一条边是在哪一层并查集被删掉的,显然 \(las[x][y]\) 只变大不减小,每次寻找踩在上一次的基础上,越到后面效率越高。

    #include<bits/stdc++.h>
    #define F(i,l,r) for(int i(l);i<=r;++i)
    using namespace std;
    const int N=3e5+5;
    struct node{
    int u,v,w,id;
    inline bool operator < (const node &other )const{ return w>other.w; }
    }e[N];
    int n,m,k,fa[10005][1005],ans[N],las[1005][1005];
    inline int get(int x,int dep){return (fa[dep][x]==x)?x:fa[dep][x]=get(fa[dep][x],dep); }
    inline bool merge(int x,int y,int dep){
    int fx=get(x,dep),fy=get(y,dep);
    if(fx==fy) return false;
    fa[dep][fx]=fy;
    return true;
    }
    signed main(){
    // freopen("a.in","r",stdin);
    // freopen("a.out","w",stdout);
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n>>m>>k;
    F(i,1,m) {
    int u,v,w;
    cin>>u>>v>>w;
    e[i]=(node){u,v,w,i};
    }
    F(i,0,k) F(j,1,n) fa[i][j]=j;//init
    std::sort(e+1,e+m+1);
    memset(ans,0,sizeof(ans));
    F(i,1,m){
    int u=e[i].u,v=e[i].v,id=e[i].id;
    if(u>v) swap(u,v);
    while(las[u][v]<=k && !merge(u,v,las[u][v])) ++las[u][v];
    ans[id]=(las[u][v]>=k)?0:++las[u][v];
    }
    F(i,1,m) cout<<ans[i]<<'\n';
    return 0;
    }

B-黑白棋盘

  • 一句话题面:每次任选一对 \((i,j)\), 用第 \(i\) 行去覆盖第 \(j\) 列,问涂成全黑的最少操作次数。
  • 不难发现存在一行全黑能全涂成全黑的充要条件。
  • 若已经存在一行全黑了,那么操作次数就是非全黑的列数。
  • 则现在问题转换成了:如何尽快涂出一行全黑?
  • 对于第 \(i\) 行,要想涂成全黑,只需要第 \(i\) 列上存在黑点即可。
  • num[i] 表示第 \(i\) 行上白点个数, col[i] 表示第 \(i\) 列上黑点个数,那么将第 \(i\) 行变成全黑得代价是:
\[num[i]+(col[i]>0)
\]
  • 那第 \(i\) 列上不存在黑点呢?则需要额外一次操作来造一个黑。

  • 因此 -1 的情况也浮出水面了:当且仅当棋盘全白

  • 那么逻辑链中还有最后一个问题:在变出一行全黑的过程中,非全黑列数是否会改变?

  • 不会,因为存在一行全黑能全涂成全黑的充要条件。

  • 算法思路如上。

  • 考场上应该优先多想一下的!毕竟放在第2题的位置,不要害怕时间不够!

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
using namespace std;
const int N=1005;
char s[N][N];
int num[N],col[N];
int n,cnt=0,tag=0,ans=1e9;
signed main(){
// freopen("b.in","r",stdin);
// freopen("b.out","w",stdout);
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n;
F(i,1,n) cin>>(s[i]+1);
F(i,1,n) F(j,1,n){
if(s[i][j]=='#') col[j]++,tag=1;//col[j]:the number of black in column <j>
else ++num[i];
}
if(!tag) return cout<<"-1",0;
F(i,1,n) if(col[i]!=n) ++cnt;//the number of column in which there is at least one white.
F(i,1,n) ans=min(ans,cnt+num[i]+(col[i]==0));
cout<<ans;
return 0;
}

upd:2024/03/22

C-序列

  • 一句话题面:给定两个数 \(n, m\),求有多少长度为 \(2m\) 的序列 \(A\) 满足 :

    1. \(A\) 中每个元素都是 \(n\) 的因数

    2. \(A\) 所有项的乘积不超过 \(n^m\) 。答案对 \(998244353\) 取模。

  • 【标签】转化(容斥)、数学、动态规划

  • 注意到乘积最大是 \(n^{2m}\), 所以每一种乘积小于 \(n^m\) 的方案都对应着一种乘积大于 \(n^m\) 的方案。

  • 即这两类方案一一对应,数量相等。

  • 记乘积等于 \(n^m\) 的方案数为 \(tot\), 不限制总乘积,只满足限制1的方案数为 \(sum\). 那么答案即为:

\[\frac{tot+sum}{2}
\]
  • 问题转化为了如何求 \(tot\).
  • 先对 \(n\) 进行质因数分解,根据 算术唯一分解定理,\(n=\sum{p_k^{a_k}}\)
  • 不难发现每个质因子的贡献是独立的。
  • 对于质因子 \(p_k\), 记 \(f[i][j]\) 表示截止第 \(i\) 个位置上一共用了 \(j\) 个该质因子的方案数,则有转移:
\[f[i][j]=\sum_{p=j-a[k]}^{j} f[i-1][p]
\]
  • \(f[2m][m*a[k]]\) 即为每个质因子对答案的贡献。相乘即为 \(sum\).

  • 边界条件为 \(f[i][0]=1\).

  • 两个优化:1.第一位可以滚动数组 2.前缀和(有点儿难写,比赛建议不用前缀和写)

我的写法:

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
const int N=1e6+5;
const int mod=998244353;
int p[N],a[N],f[N],sum[N];
int n,m,cnt=0,ans=1,tot=1,cz=1;
signed main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>m;
int x=n;
for(int i=2;i<=n&&x>1;++i){
if(x%i==0){
p[++cnt]=i;
while(x%i==0) ++a[cnt],x/=i;
cz=(1ll*cz*(a[cnt]+1))%mod;
}
}
F(k,1,cnt){//every prime
memset(sum,0,sizeof(sum));
memset(f,0,sizeof(f));
F(i,0,a[k]*m) sum[i]=i+1;
F(i,2,2*m){
F(j,1,(a[k]*m)){
if(j<=a[k]) f[j]=sum[j];
else f[j]=(1ll*sum[min((i-1)*a[k],j)]-sum[j-a[k]-1])%mod;
}
sum[0]=1; F(j,1,m*a[k]) sum[j]=(1ll*sum[j-1]+f[j])%mod;
}
ans=(1ll*ans*f[a[k]*m])%mod;
}
F(i,1,2*m) tot=(1ll*tot*cz)%mod;
cout<<((1ll*tot+ans)%mod*499122177%mod+mod)%mod;
return 0;
}

STD写法:

	F(k,1,cnt){//every prime
memset(f,0,sizeof(f));
f[0]=1;
F(i,1,2*m){
sum[0]=1; F(j,1,m*a[k]) sum[j]=(1ll*sum[j-1]+f[j])%mod;
F(j,1,a[k]*m)
f[j]=(1ll*sum[j]-(j-a[k]-1<0?0:sum[j-a[k]-1]))%mod;
}
ans=(1ll*ans*f[a[k]*m])%mod;
}
  • 反思:考场上应该先不加前缀和,最后要优化再加。

NOIP2024模拟3:一路破冰的更多相关文章

  1. 清澄 A1485. Catch The Penguins 抓企鹅

    试题来源 2013中国国家集训队论文答辩 问题描述 Xyz带着他的教徒们乘着科考船一路破冰来到了南极大陆,发现这里有许许多多的企鹅.邪恶的Xyz想要抓很多企鹅回去开动物园,当宠物玩.但动物保护协会很快 ...

  2. 用Fiddler模拟低速网络环境

    有时候宽频网路用习惯了… 在开发的过程就比较少去考虑最佳化的问题… 但当有人反应说「你的网页好慢」甚至当网路速度慢,会造成你的网页跳出什么啊哩不哒的bug时要如何重现呢? 我们可以用Fiddler 这 ...

  3. Android利用HttpURLConnection实现模拟登录

    最近在做一个APP,需要模拟登录教务处,之前曾经用HttpClient做过,点这里,但是发现最新的Android SDK已经不支持Httpclient了,所以只好在琢磨一下HttpURLConnect ...

  4. 这一路走来,冷暖自知 (附算法demos)

    最近半年多,除了“一键修图”算法之外我还做了其他什么算法? 1.实时单图HDR算法(颜色矫正,智能曝光) 2.多图曝光融合HDR算法(最高支持八百万像素左右) 3.模拟热能探测算法 4.防伪探测算法 ...

  5. 模拟Vue之数据驱动5

    一.前言 在"模拟Vue之数据驱动4"中,我们实现了push.pop等数组变异方法. 但是,在随笔末尾我们提到,当pop.sort这些方法触发后,该怎么办呢?因为其实,它们并没有往 ...

  6. STM32F207 两路ADC连续转换及GPIO模拟I2C给MT9V024初始化参数

    1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯 ...

  7. 如何使用python来模拟鼠标点击(将通过实例自动化模拟在360浏览器中自动搜索"python")

    一.准备工作: 安装pywin32,后面开发需要pywin32的支持,否则无法完成与windows层面相关的操作. pywin32的具体安装及注意事项: 1.整体开发环境: 基于windows7操作系 ...

  8. UI自动化测试(四)AutoIT工具使用和robot对象模拟键盘按键操作

    AutoIT简介 AutoIt 目前最新是v3版本,这是一个使用类似BASIC脚本语言的免费软件,它设计用于Windows GUI(图形用户界面)中进行自动化操作.它利用模拟键盘按键,鼠标移动和窗口/ ...

  9. 洛谷 P1598 垂直柱状图【字符串+模拟】

    P1598 垂直柱状图 题目描述 写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过72个字符),然后用柱状图输出每个字符在输入文件中出现的次数.严格地按照输出样例来安排你的输出格式. ...

  10. SoDiaoEditor电子病历编辑器更新至V3版本,愿与各位一路同行!

    简单闲聊两句-- 记得刚参加工作那会儿,去医院实施,信息科不远处就是手术室,门口每天都挤满了人,他们中大多数都是等待手术结果的患者家属,有的还会把折叠床带来,应该是陪床有段时间了.有时路过,还会听到一 ...

随机推荐

  1. 【主席树】P3834 【模板】可持久化线段树 2

    P3834 [模板]可持久化线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include <bits/stdc++.h> using namespace ...

  2. String, StringBuffer 和 StringBuilder之间的区别

    String, StringBuffer 和 StringBuilder 可变性 String不可变 StringBuffer 和 StringBuilder 可变 线程安全 String 不可变,因 ...

  3. Daph:新一代流批一体数据集成与数据处理工具

    Daph源码位于gitee,地址是https://gitee.com/dasea96/daph 概述 Daph的中文名称是大副,大副是职位仅低于船长的船舶驾驶员,甲板部(驾驶部)负责人,船长的主要助手 ...

  4. AI驱动的PlantUML:快速生成专业级UML图表

    **对于程序员来说,编写验收文档中的各种UML图是最让人头疼的事情之一,相信各位读者对此深有体会.** 本文将探讨如何利用AI驱动的PlantUML来快速生成专业级别的UML图表,从而减轻这一负担. ...

  5. macOS 移除顽固打印机信息

    问题描述 当我打开 Parallels Desktop 的 Ubuntu 虚拟机时,总是会看到打印机已添加的提示: 查看已有打印机信息 $ lpstat -p 打印机Lenovo_M7206W闲置,启 ...

  6. 【selenium + python】之BSTestRunner生成测试报告时报错:NameError: name 'unicode' is not defined

    好久没生成报告了,最近使用的时候报了一个错误!用的这个报告模板BSTestRunner但是汇报下面的错误: NameError: name 'unicode' is not defined 经查询得知 ...

  7. Java Pom两个模块需要互相引用怎么办

    1. Java POM模块化是什么 在Java项目中,特别是在使用Maven作为构建工具时,"POM模块化"是一个重要的概念,它指的是将大型项目拆分成多个更小.更易于管理的模块(或 ...

  8. 邀请参与第四季度 Flutter 开发者调查

    本次调研会较为详细地了解大家对 Flutter 框架.开发语言.package 生态 (包括 Firebase package).IDE 插件以及 Material Design / Cupertin ...

  9. Hive--hbase--spark

    hive创建hbase表 create external table events.hb_train( row_key string, user_id string, event_id string, ...

  10. 一些rand()的测试

    rand()生成的伪随机数已经足够我们实用,为了跟好的理解rand()跟seed的关系,做了一些测试! rand()函数种子默认为1,在每一次程序运行中,随机数相同,在一次运行中,可将生成数看做随机 ...