『模拟赛』多校A层冲刺NOIP2024模拟赛03
Rank
炸了,触底反弹
A. 五彩斑斓(colorful)
签,又没签上。
考虑如何一步步优化暴力。最暴力的思想
考虑正解,依旧容斥,我们可以直接枚举两行,再枚举列,记录每一个相同颜色组成的点对出现的数量,简单组合计数可知对于
据说有
点击查看代码
#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 fi first
#define se second
const int Ratio = 0;
const int N = 400 + 5;
const int mod = 998244353;
int n, m;
int c[N][N], tim[N * N];
ll ans;
namespace Wisadel
{
short main()
{
freopen("colorful.in", "r", stdin) , freopen("colorful.out", "w", stdout);
n = qr, m = qr;
fo(i, 1, n) fo(j, 1, m) c[i][j] = qr;
ans = 1ll * n * (n + 1) * m * (m + 1) / 4;
fo(i, 1, n) fo(j, i, n)
{
fo(k, 1, m) if(c[i][k] == c[j][k]) tim[c[i][k]]++, ans -= tim[c[i][k]];
fo(k, 1, m) if(c[i][k] == c[j][k]) tim[c[i][k]] = 0;
}
printf("%lld\n", ans);
return Ratio;
}
}
signed main(){return Wisadel::main();}
B. 错峰旅行(travel)
签,双没签上。
看到第一感觉是动态开点线段树,不过赛时怎么压都过不了最后一个大样例,卡到极限 70pts,自己画蛇添足唐错挂 10pts。
其实是可以用线段树做的。首先很显然的是,对于一段时间
点击查看代码
#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 fi first
#define se second
const int Ratio = 0;
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
int n, m, s, t, tot, ans = 1;
int v[N * 20], son[N * 20][2];
namespace Wisadel
{
int Wqp(ll x, int y)
{
int res = 1;
while(y){if(y & 1) res = 1ll * res * x % mod; x = x * x % mod; y >>= 1;}
return res;
}
#define ls (son[rt][0])
#define rs (son[rt][1])
#define mid ((l + r) >> 1)
void Wupd(int rt, int l, int r, int x, int y)
{
if(x <= l && r <= y)
{
v[rt]--;
return;
}
if(x <= mid)
{
if(!ls) ls = ++tot;
Wupd(ls, l, mid, x, y);
}
if(y > mid)
{
if(!rs) rs = ++tot;
Wupd(rs, mid + 1, r, x, y);
}
}
void Wq(int rt, int l, int r, int now)
{
if(!rt)
{
ans = 1ll * ans * Wqp(now, r - l + 1) % mod;
return;
}
if(ls || rs) Wq(ls, l, mid, now + v[rt]), Wq(rs, mid + 1, r, now + v[rt]);
else ans = 1ll * ans * Wqp(now + v[rt], r - l + 1) % mod;
}
short main()
{
freopen("travel.in", "r", stdin) , freopen("travel.out", "w", stdout);
n = qr, m = qr, s = qr, t = qr;
t -= s - 1;
tot = 1, v[1] = n;
fo(i, 1, m)
{
int x = qr, l = qr - s + 1, r = qr - s + 1;
Wupd(1, 1, t, l, r);
}
Wq(1, 1, t, 0);
printf("%d\n", ans);
return Ratio;
}
}
signed main(){return Wisadel::main();}
正解给出的是差分的思想,也很简单,有用的信息最多
点击查看代码
#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 fi first
#define se second
const int Ratio = 0;
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
int n, m, s, t, tot, ans = 1;
pii p[N << 1];
namespace Wisadel
{
int Wqp(ll x, int y)
{
int res = 1;
while(y){if(y & 1) res = 1ll * res * x % mod; x = x * x % mod; y >>= 1;}
return res;
}
short main()
{
freopen("travel.in", "r", stdin) , freopen("travel.out", "w", stdout);
n = qr, m = qr, s = qr, t = qr;
fo(i, 1, m)
{
int x = qr, l = qr, r = qr;
p[++tot] = {l, -1}, p[++tot] = {r + 1, 1};
}
sort(p + 1, p + 1 + tot);
p[0] = {s, 0};
p[++tot] = {t + 1, 0};
fo(i, 0, tot - 1)
{
n += p[i].se;
if(p[i].fi != p[i + 1].fi)
ans = 1ll * ans * Wqp(n, p[i + 1].fi - p[i].fi) % mod;
}
printf("%d\n", ans);
return Ratio;
}
}
signed main(){return Wisadel::main();}
C. 线段树(segment)
签(?),叒没签上。
还以为真是线段树,赛时脑子被禁锢了转不了,暴力都没写出来。
据 wang54321 说这是他们暑假第二场模拟赛原题。
正解区间 dp。考虑维护包含
边界处理上,初始化
点击查看代码
#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 fi first
#define se second
const int Ratio = 0;
const int N = 500 + 5;
const int mod = 1e9 + 7;
int n, m;
int sum[N][N], f[N][N];
namespace Wisadel
{
short main()
{
// freopen(".in", "r", stdin) , freopen(".out", "w", stdout);
freopen("segment.in", "r", stdin) , freopen("segment.out", "w", stdout);
n = qr, m = qr;
memset(f, 0x3f, sizeof f);
fo(i, 1, m)
{
int a = qr, b = qr;
sum[a][b]++;
}
fo(i, 1, n) fu(j, n, i) sum[i][j] += sum[i][j + 1];
fo(j, 1, n) fo(i, 1, j) sum[i][j] += sum[i - 1][j];
fo(i, 1, n) f[i][i] = sum[i][i];
fo(len, 2, n) fo(l, 1, n - len + 1)
{
int r = l + len - 1;
fo(k, l, r - 1)
f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] - sum[l][r]);
}
printf("%d\n", f[1][n]);
return Ratio;
}
}
signed main(){return Wisadel::main();}
D. 量子隧穿问题(experiment)
叕没做出来(?)
一个 trick 是计数转概率,答案
这样一来,盒子的状态可以得出有猫的概率,状态转移方程如下:
然后就可以做 dp 了。吗?
显然这么简单就不至于放 T4 了。发现每个隧道有可能连成环,整个图是一个基环树。当
注意由于 巴甫洛夫的狗 是从 1 到
点击查看代码
#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 fi first
#define se second
const int Ratio = 0;
const int N = 1e5 + 5;
const int mod = 1e9 + 7;
int n, m;
int to[N], p[N], fx[N];
bool in[N];
string s;
namespace Wisadel
{
int Wfind(int x)
{
if(x == fx[x]) return x;
return fx[x] = Wfind(fx[x]);
}
short main()
{
freopen("experiment.in", "r", stdin) , freopen("experiment.out", "w", stdout);
int T = qr;
while(T--)
{
n = qr; cin >> s;
memset(in, 0, sizeof in);
fo(i, 1, n) to[i] = qr, fx[i] = i;
int st = 0, ans = 0;
fo(i, 1, n) fx[Wfind(i)] = Wfind(to[i]);
fo(i, 1, n) in[i] = (Wfind(i) == Wfind(n));
fo(i, 1, n) fx[i] = i;
fu(i, n, 1)
{
int _ = Wfind(i), __ = Wfind(to[i]);
if(in[i] && _ != __) fx[_] = __;
else if(in[i]) st = i;
}
fo(x, 0, 1) fo(y, 0, 1)
{
fo(i, 0, n - 1)
if(s[i] == 'C') p[i + 1] = 1;
else if(s[i] == '.') p[i + 1] = 0;
else p[i + 1] = (1 + mod) / 2;
int res = 1;
fo(i, 1, n)
{
if(i == st)
{
res = 1ll * (x ? p[i] : (1 - p[i])) * (y ? p[to[i]] : (1 - p[to[i]])) % mod;
p[i] = x;
p[to[i]] = y;
}
int xx = p[i], yy = p[to[i]];
p[i] = 1ll * xx * yy % mod;
p[to[i]] = (1ll * yy + 1ll * xx * (1 - yy) % mod) % mod;
}
ans = (ans + 1ll * res * p[n] % mod) % mod;
}
fo(i, 0, n - 1) if(s[i] == '?') ans = ans * 2 % mod;
printf("%d\n", (ans + mod) % mod);
}
return Ratio;
}
}
signed main(){return Wisadel::main();}
末
怀疑这个出题人看过 某人 和 某人 的唐博,开幕巴甫洛夫的狗雷击整个机房。
挺烂的,作为 17 岁 的开局有点糟糕,希望低开高走吧。
一整天状态不太好,好在下午及时调整过来了。
今天的超链接好像放的过于多了
完结撒花~
最后再祝自己生日快乐!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探