『模拟赛』多校A层冲刺NOIP2024模拟赛18
Rank
打成大奋了
A. 选彩笔(rgb)
签 我是彩笔
赛时完全不会啊,打了一个 25k 的贪心结果爆栈了喜提 0pts。
最大值最小,还是二分答案。二分的答案是最大差,发现值域很小,我们在 check 时可以直接枚举每个色号的最大值,统计在所选区间范围内笔数。这样就有了
考虑三维前缀和优化,
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(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 P_B(x) push_back(x)
const int Ratio = 0;
const int N = 1e5 + 5;
int n, m, ans;
struct rmm{int r, g, b, id;} p[N];
int sum[260][260][260];
namespace Wisadel
{
ll Wq(int i, int j, int k, int mid)
{
ll res = sum[i][j][k];
if(i >= mid)
{
if(j >= mid)
{
if(k >= mid) res -= sum[i - mid][j - mid][k - mid];
res += sum[i - mid][j - mid][k];
}
if(k >= mid) res += sum[i - mid][j][k - mid];
res -= sum[i - mid][j][k];
}
if(j >= mid)
{
if(k >= mid) res += sum[i][j - mid][k - mid];
res -= sum[i][j - mid][k];
}
if(k >= mid) res -= sum[i][j][k - mid];
return res;
}
bool Wck(int tar)
{
fo(i, tar - 1, 255) fo(j, tar - 1, 255) fo(k, tar - 1, 255)
if(Wq(i, j, k, tar) >= m) return 1;
return 0;
}
short main()
{
freopen("rgb.in", "r", stdin), freopen("rgb.out", "w", stdout);
n = qr, m = qr;
fo(i, 1, n) p[i].r = qr, p[i].g = qr, p[i].b = qr, sum[p[i].r][p[i].g][p[i].b]++;
fo(i, 1, 255) fo(j, 0, 255) fo(k, 0, 255) sum[i][j][k] += sum[i - 1][j][k];
fo(i, 0, 255) fo(j, 1, 255) fo(k, 0, 255) sum[i][j][k] += sum[i][j - 1][k];
fo(i, 0, 255) fo(j, 0, 255) fo(k, 1, 255) sum[i][j][k] += sum[i][j][k - 1];
int l = 0, r = 255, ans = 255;
while(l <= r)
{
int mid = (l + r) >> 1;
if(Wck(mid + 1)) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%d\n", ans);
return Ratio;
}
}
signed main(){return Wisadel::main();}
B. 兵蚁排序(sort)
也很水的一个题,赛时因为 T1 想假了耽误很长时间所以没多想,推出一个假性质居然能模过所有样例,但是假,所以 30pts。
先说说赛时的假做法:首先因为发现了大的数不可能往前走,所以我是倒着做的,考虑扫到的每一个数:比
那么根据这个错误,推出一个有正确性的做法:正着扫,然后对于当前序列向前扫到第一个等于
复杂度
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(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
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 1e5 + 5;
int n;
int a[N], b[N];
multiset<int> st;
vector<pii> ans;
namespace Wisadel
{
short main()
{
freopen("sort.in", "r", stdin), freopen("sort.out", "w", stdout);
int T = qr;
while(T--)
{
n = qr; ans.clear();
fo(i, 1, n) a[i] = qr;
fo(i, 1, n) b[i] = qr;
bool bok = 0;
fo(i, 1, n)
{
int zc = 0;
fo(j, i, n) if(b[i] == a[j]){zc = j; break;}
fu(j, zc, i + 1)
{
if(a[j] < a[j - 1])
{
ans.P_B(M_P(j - 1, j));
swap(a[j], a[j - 1]);
}
else{bok = 1; break;}
}
if(bok) break;
}
if(bok) puts("-1");
else
{
puts("0");
printf("%d\n", ans.size());
for(auto i : ans) printf("%d %d\n", i.fi, i.se);
}
}
return Ratio;
}
}
signed main(){return Wisadel::main();}
C. 人口局 DBA(dba)
推柿子题。
看到的第一反应就是数位 dp,然而看一会你就会发现时间空间都是假的。然后把暴力交上去有 22pts。
考虑如何简化问题。依然从数位 dp 的过程思考,当 limit=0 时,我们此后选数没有任何障碍,也就转化成了一个计数问题:共
我们设
此时考虑加上 limit 的限制。由于题目要求
开推:
我们设
结合杨辉三角来表示,可以将其化为:
代回原来的式子,得:
考虑代回原题,我们每次多固定一位等于原位上的数,那么此时答案即为
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(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
#define M_P(x, y) make_pair(x, y)
#define P_B(x) push_back(x)
const int Ratio = 0;
const int N = 2000 + 5;
const int mod = 1e9 + 7;
int n, m;
int a[N], zc[N], tot;
ll jc[N * N], ny[N * N], ans;
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)
{
if(n < m) return 0;
return jc[n] * ny[m] % mod * ny[n - m] % mod;
}
short main()
{
freopen("dba.in", "r", stdin), freopen("dba.out", "w", stdout);
m = qr, n = qr;
fo(i, 1, n) a[i] = qr, tot += a[i];
jc[0] = ny[0] = 1;
fo(i, 1, n * m) jc[i] = jc[i - 1] * i % mod;
ny[n * m] = Wqp(jc[n * m], mod - 2);
fu(i, n * m - 1, 1) ny[i] = ny[i + 1] * (i + 1) % mod;
fo(i, 1, n)
{
fo(k, 0, n - i)
{
int op = (k & 1) ? -1 : 1;
ans = (ans + (1ll * op * Wc(n - i, k) % mod + mod) % mod * ((Wc(tot - k * m + n - i, n - i) - Wc(tot - k * m + n - i - a[i], n - i) + mod) % mod) % mod) % mod;
}
tot -= a[i];
}
printf("%lld\n", ans);
return Ratio;
}
}
signed main(){return Wisadel::main();}
D. 银行的源起(banking)
不会。
赛时想到找重心分开再找重心,然后发现还有居民就不会了,打了
末
打的依托,T1 上来没思路就很伤,然后想了一个需要打巨大长代码的假思路更伤,结果是导致本来能切两题的场一题没切,暴力还没拿满。
学到的东西太不牢固导致一遇到需要结合多一点东西的题就发懵,维持有效状态的时间短是很重要的一个原因。
huge 晚上来开小会。内务纪律扯🥚不提,但 noip 真可能是我最后一场作为全职 OIer 的比赛了。不说像初见 OI 时那样一定冲金夺银的豪言壮语,多少也要给自己这一年多的时间一个交代,我到底有没有成长,我的实力究竟如何。挂分再怎么不应该也是挂了,没人会听你本来该能多少分,别人看到的只是最终的结果,当然,你自己真正在意的也是。所以拿出最好的状态,打一场酣畅淋漓的比赛才是最好的结果。不知道说这些能不能对自己有点影响,但是真的到了该拼的时候了,加油!
不知道会不会完结撒花~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探