[蓝桥杯 2020 国 B] 质数行者
前言
也是终于做到了
思路
首先考虑暴力
显然的我们可以暴力做
考虑优化
你注意到只有两个障碍点, 这个好像很重要
考虑「容斥原理」, 正难则反, 记
然后考虑
因为直接
首先我们发现, 这种问题很像之前的经典问题, 在之前的问题中
即在
但是这个问题之中, 要求每次走的长度为质数, 怎么处理?
还是考虑操作次数中做组合数, 考虑预处理出
先考虑
考虑
这个
这个多半只能对柿子进行优化, 考虑减少
拆!
你注意到这个可以预处理的方式去做到
具体的, 预处理
感觉暴力
然而枚举状态
实现
框架#
这个题代码偏长, 抄
首先处理
来处理
常见的错误:
枚举
代码#
#include <bits/stdc++.h>
#define int long long
const int MOD = 1e9 + 7;
const int MAXW = 520; // 641
const int MAXVAL = 1020;
const int MAXNUM = 1e6 + 20, NUM = 1e6;
/*1000 以内的质数*/
int prime[] = {
}, cnt = 168;
int fac[MAXNUM], ifac[MAXNUM];
int add(int a, int b) { return a + b > MOD ? a + b - MOD : a + b; }
int sub(int a, int b) { return a - b < 0 ? a - b + MOD : a - b; }
int mul(int a, int b) { return (a * b * 1ll) % MOD; }
void addon(int &a, int b) { a = add(a, b); }
void mulon(int &a, int b) { a = mul(a, b); }
int quickpow(int a, int pows) {
int base = 1;
while (pows) {
if (pows & 1) mulon(base, a);
mulon(a, a), pows >>= 1;
}
return base;
}
void init()
{ fac[0] = fac[1] = 1; for (int i = 2; i <= NUM; i++) fac[i] = mul(i, fac[i - 1]);
ifac[NUM] = quickpow(fac[NUM], MOD - 2); for (int i = NUM - 1; ~i; i--) ifac[i] = mul(ifac[i + 1], i + 1); }
int n, m, w;
int r1, c1, h1, r2, c2, h2;
struct rec { int x, y, z; };
int g[MAXW][MAXVAL];
/*预处理 g*/
void gcalc() {
g[0][0] = 1;
for (int i = 1; i <= 500; i++) for (int j = 1; j <= 1000; j++)
for (int p = 1; p <= cnt; p++) {
if (prime[p] > j) break;
addon(g[i][j], g[i - 1][j - prime[p]]);
}
}
int h[MAXVAL];
int f(rec a, rec b) {
int x = b.x - a.x, y = b.y - a.y, z = b.z - a.z; if (x < 0 || y < 0 || z < 0) return 0;
memset(h, 0, sizeof h);
for (int sum = 0; sum <= x / 2 + y / 2; sum++) for (int k = 0; k <= z / 2; k++)
addon(h[sum], mul(mul(fac[sum + k], g[k][z]), ifac[k]));
int res = 0;
for (int sum = 0; sum <= x / 2 + y / 2; sum++) for (int i = 0; i <= std::min(x / 2, sum); i++) { if (sum - i > y / 2) continue;
addon(res, mul(mul(mul(g[i][x], ifac[i]), mul(g[sum - i][y], ifac[sum - i])), h[sum])); }
return res;
}
signed main()
{
scanf("%lld %lld %lld", &n, &m, &w);
scanf("%lld %lld %lld %lld %lld %lld", &r1, &c1, &h1, &r2, &c2, &h2);
rec s = {1, 1, 1}, t = {n, m, w}, u = {r1, c1, h1}, v = {r2, c2, h2};
init();
gcalc();
/*f(s, t) - [(f(s, u) * f(u, t) + f(s, v) * f(v, t)) - (f(s, u) * f(u, v) * f(v, t) + f(s, v) * f(v, u) * f(u, t))] --> ans1 - (ans2 + ans3 - ans4) */
int ans = sub(f(s, t), sub(add(mul(f(s, u), f(u, t)), mul(f(s, v), f(v, t))), add(mul(mul(f(s, u), f(u, v)), f(v, t)), mul(mul(f(s, v), f(v, u)), f(u, t)))));
printf("%lld", ans);
return 0;
}
总结
容斥原理计算非法方案数
同类型问题, 往往可以用预处理进行转化
瞎几把拆柿子有的时候会有用, 不会做了试试
这个题其实是把
vivo 50
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫