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

『模拟赛』多校A层冲刺NOIP2024模拟赛08

时间:2024-10-17 18:11:11浏览次数:6  
标签:rt qr return int 08 ch 模拟 NOIP2024 define

Rank

还行

image

A. 传送 (teleport)

签。

单元最短路,先想 Dijkstra。发现这道题还有个不同寻常的移动方式,可以以 \(min\left(|x_i-x_j|,|y_i-y_j|\right)\) 的代价从 \(i\) 移动到 \(j\)。暴力连边是 \(\mathcal{O(n^2)}\) 的,时间空间都过不去。

被叫去整内务在楼梯上想到,一个点不应该来回走,于是想到若有 \(x_i<x_j<x_k\) (假设纵坐标不优),那么我们只用连 \(i\rightarrow j\) 和 \(j\rightarrow k\) 这两条边即可。因此想到分别按横坐标和纵坐标给点排序,然后连接相邻的两点,再去跑 dij 即可。坐标共 \(2\times \left(n-1\right)\) 条边,由于是无向图,我们边的内存应该开 \(n\) 的 6 倍。时间复杂度仍是 \(\mathcal{O(n\log n)}\) 的。喜提最优解。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch = getchar();lx x = 0 , f = 1;
	for(;ch<'0'||ch>'9';ch = getchar()) if(ch == '-') f = -1;
	for(;ch>= '0' && ch<= '9';ch = getchar()) x = (x<<3) + (x<<1) + (ch^48);
	return x*f;
}
#undef lx
#define qr qr()
#define pii pair<int, int>
#define M_P(a, b) make_pair(a, b)
#define fi first
#define se second
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 2e5 + 5;
int n, m;
int hh[N], to[N << 3], ne[N << 3], w[N << 3], cnt;
ll dis[N];
bool yz[N];
struct rmm
{
	ll dis; int u;
	bool operator < (const rmm &a) const {return a.dis < dis;}
};
struct nd
{
    int id, x, y;
} d[N], dd[N];
namespace Wisadel
{
    void Wadd(int u, int v, int val)
    {
        to[++cnt] = v;
        w[cnt] = val;
        ne[cnt] = hh[u];
        hh[u] = cnt;
    }
    void Wdij(int x)
    {
		priority_queue<rmm> q;
        memset(dis, 0x3f, sizeof dis);
		dis[x] = 0;
		q.push({0, x});
		while(q.size())
		{
			int u = q.top().u; q.pop();
			if(yz[u]) continue;
			yz[u] = 1;
            for(int i = hh[u]; i != -1; i = ne[i])
            {
                int v = to[i];
                if(dis[v] > dis[u] + w[i])
                {
                    dis[v] = dis[u] + w[i];
                    q.push({dis[v], v});
                }
            }
		}
    }
    short main()
    {
        freopen("teleport.in", "r", stdin) , freopen("teleport.out", "w", stdout);
        // freopen(".err", "w", stderr);
        n = qr, m = qr;
        memset(hh, -1, sizeof hh);
        fo(i, 1, n) dd[i].x = d[i].x = qr, dd[i].y = d[i].y = qr, d[i].id = dd[i].id = i;
        sort(d + 1, d + 1 + n, [](nd a, nd b){return a.x < b.x;});
        sort(dd + 1, dd + 1 + n, [](nd a, nd b){return a.y < b.y;});
        fo(i, 1, n - 1)
        {
            int c1 = d[i + 1].x - d[i].x, c2 = dd[i + 1].y - dd[i].y;
            Wadd(d[i].id, d[i + 1].id, c1), Wadd(d[i + 1].id, d[i].id, c1);
            Wadd(dd[i].id, dd[i + 1].id, c2), Wadd(dd[i + 1].id, dd[i].id, c2);
        }
        fo(i, 1, m)
        {
            int a = qr, b = qr, c = qr;
            Wadd(a, b, c), Wadd(b, a, c);
        }
        Wdij(1);
        fo(i, 2, n) printf("%lld ", dis[i]);puts("");
        return Ratio;
    }
}
signed main(){return Wisadel::main();}

B. 排列 (permutation)

组合数学水题,状压 dp 也能做。

赛时发现不会插板法,于是选择分讨打表,但是到 \(\frac{n}{k}\ge 8\) 因为没有暴力帮忙核对导致漏情况了,血亏。调出来复杂度就是 \(\mathcal{O(n)}\) 的预处理,\(\mathcal{O(1)}\) 出答案。

发现只有 \(\lfloor{}\frac{n}{k}\rfloor{}\) 个数是有用的,其余的数无论如何放均不会产生 \(k\) 的 gcd。不过特殊的是,当 \(\frac{n}{k}\ge 4\) 时,总有一些数放在一起会产生 \(\gt k\) 的 gcd。因此我们考虑全排列枚举这 \(\lfloor{}\frac{n}{k}\rfloor{}\) 个数,记录它们间的 gcd 为 \(k\) 的个数,然后用插板法求这 \(\lfloor{}\frac{n}{k}\rfloor{}\) 个数的合法方案,最后乘上 \(n-\lfloor{}\frac{n}{k}\rfloor{}\) 的排列即为最终答案,复杂度大概是 \(\mathcal{O(\lfloor{}\frac{n}{k}\rfloor{}!\times \lfloor{}\frac{n}{k}\rfloor{}+n)}\) 的。

由于放不下赛时的做法,遂在正解中用了数据点分治。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch = getchar();lx x = 0 , f = 1;
	for(;ch<'0'||ch>'9';ch = getchar()) if(ch == '-') f = -1;
	for(;ch>= '0' && ch<= '9';ch = getchar()) x = (x<<3) + (x<<1) + (ch^48);
	return x*f;
}
#undef lx
#define qr qr()
#define pii pair<int, int>
#define M_P(a, b) make_pair(a, b)
#define fi first
#define se second
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 3e4 + 5, M = 3000;
const int mod = 998244353;
int n, k;
int a[N];
ll jc[N], ny[N];
namespace Wisadel
{
    ll Wqp(ll x, int y)
    {
        ll res = 1;
        while(y){if(y & 1) res = res * x % mod; x = x * x % mod; y >>= 1;}
        return res;
    }
    ll Wc(int n, int m)
    {
        return jc[n] * ny[m] % mod * ny[n - m] % mod;
    }
    short main()
    {
        freopen("permutation.in", "r", stdin) , freopen("permutation.out", "w", stdout);
        // freopen(".err", "w", stderr);
        n = qr, k = qr;
        jc[0] = ny[0] = 1;
        fo(i, 1, n) jc[i] = jc[i - 1] * i % mod;
        ny[n] = Wqp(jc[n], mod - 2);
        fu(i, n - 1, 1) ny[i] = ny[i + 1] * (i + 1) % mod;
        ll zc = n / k;
        ll ans = 1;
        if(zc <= 3) ans = jc[zc] * jc[n - zc] % mod * Wc(n - zc + 1, zc) % mod;
        else if(zc <= 5)
        {
            ans = jc[zc] * jc[n - zc] % mod * Wc(n - zc + 1, zc) % mod;
            ans = (ans + jc[zc - 1] * jc[n - zc] % mod * 2 * Wc(n - zc + 1, zc - 1) % mod) % mod;
        }
        else if(zc <= 7)
        {
            ans = jc[zc] * jc[n - zc] % mod * Wc(n - zc + 1, zc) % mod;
            ans = (ans + jc[zc - 1] * jc[n - zc] % mod * 2 % mod * Wc(n - zc + 1, zc - 1) % mod * 4 % mod) % mod;

            ans = (ans + jc[zc - 2] * jc[n - zc] % mod * 6 % mod * Wc(n - zc + 1, zc - 2) % mod) % mod;
            ans = (ans + jc[zc - 2] * jc[n - zc] % mod * 4 % mod * Wc(n - zc + 1, zc - 2) % mod) % mod;
            ans = (ans + jc[zc - 2] * jc[n - zc] % mod * 2 % mod * Wc(n - zc + 1, zc - 2) % mod * 2 % mod) % mod;

            ans = (ans + jc[zc - 3] * jc[n - zc] % mod * 4 % mod * Wc(n - zc + 1, zc - 3) % mod) % mod;
        }
        else
        {
            ans = 0;
            fo(i, 1, zc) a[i] = i;
            do
            {
                int cnt = 0;
                fo(i, 1, zc - 1) if(__gcd(a[i], a[i + 1]) == 1) cnt++;
                ans = (ans + Wc(n - cnt, zc)) % mod;
            } while(next_permutation(a + 1, a + 1 + zc));
            ans = ans * jc[n - zc] % mod;
        }
        printf("%lld\n", ans);
        return Ratio;
    }
}
signed main(){return Wisadel::main();}

C. 战场模拟器 (simulator)

没学过势能线段树,不知道这样复杂度是正确的,遂没敢打,只打了 Subtask2 的 23pts。

发现这道题主要是死人不复活和护盾比较 ex,因此我们针对这两点直接暴力做就好。如果你打了 Subtask2,那么应该知道为什么要记录区间最小生命值及其数量,没打也能懂:因为每次扣血操作我们是暴力进行的,只有求濒死人数才用到最小值且只用到最小值。然后记录区间死亡人数,以及一个 lazy tag。我们发现,当区间没有盾并且打不死最小生命的英雄时我们没必要递归到单点做,因此再记录一个区间盾数量。

除了扣血,其它操作都是基本的线段树操作。在求濒死人数时还可以根据当前最小值是否 \(\gt 0\) 来节省递归的次数。

问题主要在证明这个做法的时间复杂度正确性,搜索发现并没有太好的讲解。于是只能感性理解:每个点的操作都是有上限的,在达到这个上限后便不用再进行单点修改,这样就保证了均摊复杂度。求复杂度好像用到了势能函数,不会,只给出结果:\(\mathcal{O(n\log n + 4n\log (势能))}\)。本题的复杂度是 \(\mathcal{O(n\log n+q\log n)}\) 的。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch = getchar();lx x = 0 , f = 1;
	for(;ch<'0'||ch>'9';ch = getchar()) if(ch == '-') f = -1;
	for(;ch>= '0' && ch<= '9';ch = getchar()) x = (x<<3) + (x<<1) + (ch^48);
	return x*f;
}
#undef lx
#define qr qr()
#define pii pair<int, int>
#define M_P(a, b) make_pair(a, b)
#define fi first
#define se second
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 2e5 + 5, M = 3000;
const int mod = 998244353;
int n, m;
int a[N];
int a1[N << 2], dun[N << 2], num[N << 2];
ll s[N << 2], lazy[N << 2];
namespace Wisadel
{
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    #define mid ((l + r) >> 1)
    void Wpushup(int rt)
    {
        a1[rt] = a1[ls] + a1[rs];
        dun[rt] = dun[ls] + dun[rs];
        s[rt] = min(s[ls], s[rs]);
        num[rt] = 0;
        if(s[ls] == s[rt]) num[rt] += num[ls];
        if(s[rs] == s[rt]) num[rt] += num[rs];
    }
    void Wpushdown(int rt)
    {
        s[ls] += lazy[rt], s[rs] += lazy[rt];
        lazy[ls] += lazy[rt], lazy[rs] += lazy[rt];
        lazy[rt] = 0;
    }
    void Wbuild(int rt, int l, int r)
    {
        if(l == r)
        {
            s[rt] = a[l];
            num[rt] = 1;
            return ;
        }
        Wbuild(ls, l, mid), Wbuild(rs, mid + 1, r);
        Wpushup(rt);
    }
    void Watk(int rt, int l, int r, int x, int y, int k)
    {
        if(x <= l && r <= y && s[rt] >= k && !dun[rt])
        {
            s[rt] -= k, lazy[rt] -= k;
            return ;
        }
        if(l == r)
        {
            if(dun[rt]) dun[rt]--;
            else a1[rt] = 1, num[rt] = 0, s[rt] = 4e18;
            return ;
        }
        if(lazy[rt]) Wpushdown(rt);
        if(x <= mid) Watk(ls, l, mid, x, y, k);
        if(y > mid) Watk(rs, mid + 1, r, x, y, k);
        Wpushup(rt);
    }
    void Wrec(int rt, int l, int r, int x, int y, int k)
    {
        if(x <= l && r <= y)
        {
            s[rt] += k, lazy[rt] += k;
            return ;
        }
        if(lazy[rt]) Wpushdown(rt);
        if(x <= mid) Wrec(ls, l, mid, x, y, k);
        if(y > mid) Wrec(rs, mid + 1, r, x, y, k);
        Wpushup(rt);
    }
    void Wdun(int rt, int l, int r, int x)
    {
        if(l == r)
        {
            dun[rt]++;
            return ;
        }
        if(lazy[rt]) Wpushdown(rt);
        if(x <= mid) Wdun(ls, l, mid, x);
        else Wdun(rs, mid + 1, r, x);
        Wpushup(rt);
    }
    int Wq1(int rt, int l, int r, int x, int y)
    {
        if(x <= l && r <= y) return a1[rt];
        if(lazy[rt]) Wpushdown(rt);
        int res = 0;
        if(x <= mid) res += Wq1(ls, l, mid, x, y);
        if(y > mid) res += Wq1(rs, mid + 1, r, x, y);
        return res;
    }
    int Wq2(int rt, int l, int r, int x, int y)
    {
        if(s[rt]) return 0;
        if(x <= l && r <= y) return num[rt];
        if(lazy[rt]) Wpushdown(rt);
        int res = 0;
        if(x <= mid) res += Wq2(ls, l, mid ,x, y);
        if(y > mid) res += Wq2(rs, mid + 1, r, x, y);
        return res;
    }
    short main()
    {
        freopen("simulator.in", "r", stdin) , freopen("simulator.out", "w", stdout);
        // freopen(".err", "w", stderr);
        n = qr;
        fo(i, 1, n) a[i] = qr;
        Wbuild(1, 1, n);
        m = qr;
        fo(i, 1, m)
        {
            int op = qr, l = qr, r, k;
            if(op == 1) r = qr, k = qr, Watk(1, 1, n, l, r, k);
            else if(op == 2) r = qr, k = qr, Wrec(1, 1, n, l, r, k);
            else if(op == 3) Wdun(1, 1, n, l);
            else if(op == 4) r = qr, printf("%d\n", Wq1(1, 1, n, l, r));
            else r = qr, printf("%d\n", Wq2(1, 1, n, l, r));
        }
        return Ratio;
    }
}
signed main(){return Wisadel::main();}

D. 点亮 (light)

还不会,咕咕咕。

在回了趟宿舍的干扰下打成这样感觉还行,甚至对 T1 起了正向帮助,那么______

标签:rt,qr,return,int,08,ch,模拟,NOIP2024,define
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18472838

相关文章

  • 10.17 模拟赛
    炼石计划10月01日NOIP模拟赛#7【补题】-比赛-梦熊联盟(mna.wang)复盘T1一眼不会。先打了前\(30\)的爆搜。虽然这个爆搜假了但是最后也没管它。后面的暴力分挺多。先往后做。T2\(2^{2n}\)的暴力可以过\(20\)。\(n=16\)的特殊性质可以\(3^n\)枚举子集过。......
  • NOIP2024集训Day53 图论
    NOIP2024集训Day53图论A.[BZOJ4144ANOOZ2014]Petrol首先注意到起点和终点都是加油站。假设中途经过某个非加油站的点\(u\),\(u\)连到\(v\),离\(u\)最近的加油站是\(x\),那么从\(u\)到\(x\)加油后回到\(u\),再到\(v\)一定不比直接从\(u\)到\(v\)差。因为\(u......
  • 2024/10/17 模拟赛总结
    \(100+50+0+35=185\),呃呃呃,终于吃上LRX了#A.语言考虑名词性词组的性质,由于它可以由任意名词,形容词和名词性词组拼接起来,那么连续的名词,形容词或交替出现都是可行的但是如果最后一个是形容词不可行,不然它就无法修饰其他词语了于是可以枚举那一个单独的动词,判断前面和后面知......
  • 1283 回文日期 枚举 模拟 时间
    #include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintN=1e3+10;//每个月的天数,2月暂时设为29天,后续会根据闰年和平年调整inta[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};intmain(){ints1,s2,ans=0;cin>>......
  • 多校A层冲刺NOIP2024模拟赛08
    多校A层冲刺NOIP2024模拟赛08\(T1\)A.传送(teleport)\(0pts\)弱化版:[ABC065D]Built?|luoguP8074[COCI2009-2010#7]SVEMIR|“迎新春,过大年”多校程序设计竞赛H二次元世界之寻找珂朵莉先不管后面加入的\(m\)条边。对于两点间的路径\(i\toj\),经过中......
  • 5253 铺地毯 枚举 模拟
    思路分析 1. 输入处理:程序首先读取地毯的数量n。然后依次读取每张地毯的信息,包括左下角坐标(a,b)和尺寸(c,d),并存储在数组中。 查询点的输入:读取要查询的点的坐标(x,y)。 3. 检查覆盖: 从最后一张地毯开始,依次向前检查每张地毯是否覆盖点(x,y)。 检查条......
  • Oracle 19c OCP 认证考试 083 题库(第3题)- 2024年修正版
    【优技教育】Oracle19cOCP083题库(Q3题)-2024年修正版考试科目:1Z0-083考试题量:85道(线下)通过分数:57%以上考试时间:150min(线下)本文为(CUUG原创)整理并解析,转发请注明出处,禁止抄袭及未经注明出处的转载。原文地址:http://www.cuug.com.cn/ocp/083kaoshitiku/38540354314.ht......
  • 「模拟赛」多校 A 层联训 8
    \(22pts\),本来可以切掉前两个题的?!A.传送(teleport)签到12pts,错的很唐!我把Dij用的dis数组直接赋值成了点到1号点之间的x距离和y距离的最小值,没再赋成极大值,这样会改变Dij过程中点遍历到的顺序,然后就跑不出最短路了。好像不能算挂分?但其实赛时有点感觉是这的问......
  • 使用华三模拟器架构网络的实验
    为了记一点一些常用的配置命令拓扑图如下:lldp默认是关闭的,需要在sys层使用「lldpglobalenable」开启。设备堆叠需要防止脑裂,不可低于2跟堆叠线。dhcp在全局设置开启后,需要在端口上应用地址池的IP才生效。二层端口聚合和三层端口聚合需要先设置物理端口类型点击查看三......
  • uniapp精仿支付宝UI界面,首页/理财/消息/生活/口碑/我的,还有模拟支付宝扫码支付/收付款
    uniapp精仿支付宝UI界面,首页/理财/消息/生活/口碑/我的,还有模拟支付宝扫码支付/收付款等功能,界面漂亮颜值高,视频商城小工具等,蚂蚁森林种树养鸡农场偷菜样样齐用于视频,商城,直播,聊天等sumer-alipay介绍uniapp精仿支付宝UI界面,首页/理财/消息/生活/口碑/我的,还有模拟支付宝......