第十一届蓝桥杯(国赛)——质数行者

问题描述
小蓝在玩一个叫质数行者的游戏,游戏在一个 n × m × w n×m×w n×m×w 的立体方格图上进行,

从北到南依次标号为第 1 1 1 行到第 n n n 行,从西到东依次标号为第 1 1 1 列到第 m m m 列,从下到上依次标号为第 1 1 1 层到第 w w w 层。

小蓝要控制自己的角色从第 1 1 1 行第 1 1 1 列第 1 1 1 层移动到第 n n n 行第 m m m 列第 w w w 层。

每一步,他可以向东走质数格、向南走质数格或者向上走质数格,每走到一个位置,小蓝的角色要稍作停留。

在游戏中有两个陷阱,分别为第 r 1 r1 r1 行第 c 1 c1 c1 列第 h 1 h1 h1 层和第 r 2 r2 r2 行第 c 2 c2 c2 列第 h 2 h2 h2 层,这两个陷阱可以跨过,但不能停留。

也就是说,小蓝不能控制角色某一步正好走到陷阱上,但是某一步中间跨过了陷阱是允许的。

小蓝最近比较清闲,因此他想用不同的走法来完成这个游戏。所谓两个走法不同,是指小蓝稍作停留的位置集合不同。

请帮小蓝计算一下,他总共有多少种不同的走法。

提示:请注意内存限制,如果你的程序运行时超过内存限制将不得分。

输入格式
输入第一行包含两个整数 n , m , w n, m, w n,m,w,表示方格图的大小。
第二行包含 6 6 6 个整数, r 1 , c 1 , h 1 , r 2 , c 2 , h 2 r1 , c1 , h1 , r2 , c2 , h2 r1,c1,h1,r2,c2,h2,表示陷阱的位置。

输出格式
输出一行,包含一个整数,表示走法的数量。答案可能非常大,请输出答案除以 1000000007 1000000007 1000000007 的余数。

样例输入
5 6 1
3 4 1 1 2 1

样例输出
11

样例说明
( r , c , h ) (r,c,h) (r,c,h) 表示第 r r r 行第 c c c 列第 h h h 层,可能的走法有以下几种:

  1. ( 1 , 1 , 1 ) − ( 1 , 3 , 1 ) − ( 1 , 6 , 1 ) − ( 3 , 6 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (1,3,1) − (1,6,1) − (3,6,1) − (5,6,1) (1,1,1)(1,3,1)(1,6,1)(3,6,1)(5,6,1)
  2. ( 1 , 1 , 1 ) − ( 1 , 3 , 1 ) − ( 3 , 3 , 1 ) − ( 3 , 6 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (1,3,1) − (3,3,1) − (3,6,1) − (5,6,1) (1,1,1)(1,3,1)(3,3,1)(3,6,1)(5,6,1)
  3. ( 1 , 1 , 1 ) − ( 1 , 3 , 1 ) − ( 3 , 3 , 1 ) − ( 5 , 3 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (1,3,1) − (3,3,1) − (5,3,1) − (5,6,1) (1,1,1)(1,3,1)(3,3,1)(5,3,1)(5,6,1)
  4. ( 1 , 1 , 1 ) − ( 3 , 1 , 1 ) − ( 3 , 3 , 1 ) − ( 3 , 6 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (3,1,1) − (3,3,1) − (3,6,1) − (5,6,1) (1,1,1)(3,1,1)(3,3,1)(3,6,1)(5,6,1)
  5. ( 1 , 1 , 1 ) − ( 3 , 1 , 1 ) − ( 3 , 3 , 1 ) − ( 5 , 3 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (3,1,1) − (3,3,1) − (5,3,1) − (5,6,1) (1,1,1)(3,1,1)(3,3,1)(5,3,1)(5,6,1)
  6. ( 1 , 1 , 1 ) − ( 3 , 1 , 1 ) − ( 5 , 1 , 1 ) − ( 5 , 3 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (3,1,1) − (5,1,1) − (5,3,1) − (5,6,1) (1,1,1)(3,1,1)(5,1,1)(5,3,1)(5,6,1)
  7. ( 1 , 1 , 1 ) − ( 3 , 1 , 1 ) − ( 5 , 1 , 1 ) − ( 5 , 4 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (3,1,1) − (5,1,1) − (5,4,1) − (5,6,1) (1,1,1)(3,1,1)(5,1,1)(5,4,1)(5,6,1)
  8. ( 1 , 1 , 1 ) − ( 1 , 4 , 1 ) − ( 1 , 6 , 1 ) − ( 3 , 6 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (1,4,1) − (1,6,1) − (3,6,1) − (5,6,1) (1,1,1)(1,4,1)(1,6,1)(3,6,1)(5,6,1)
  9. ( 1 , 1 , 1 ) − ( 1 , 6 , 1 ) − ( 3 , 6 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (1,6,1) − (3,6,1) − (5,6,1) (1,1,1)(1,6,1)(3,6,1)(5,6,1)
  10. ( 1 , 1 , 1 ) − ( 3 , 1 , 1 ) − ( 3 , 6 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (3,1,1) − (3,6,1) − (5,6,1) (1,1,1)(3,1,1)(3,6,1)(5,6,1)
  11. ( 1 , 1 , 1 ) − ( 3 , 1 , 1 ) − ( 5 , 1 , 1 ) − ( 5 , 6 , 1 ) (1,1,1) − (3,1,1) − (5,1,1) − (5,6,1) (1,1,1)(3,1,1)(5,1,1)(5,6,1)

数据范围
对于 30% 的评测用例, 1 ≤ n , m , w ≤ 50 。 1 ≤ n,m,w ≤ 50。 1n,m,w50
对于 60% 的评测用例, 1 ≤ n , m , w ≤ 300 。 1 ≤ n,m,w ≤ 300。 1n,m,w300
对于所有评测用例, 1 ≤ n , m , w ≤ 1000 , 1 ≤ r 1 , r 2 ≤ n , 1 ≤ c 1 , c 2 ≤ m , 1 ≤ h 1 , h 2 ≤ w 1 ≤ n,m,w ≤ 1000,1 ≤ r 1 ,r 2 ≤ n, 1 ≤ c 1 ,c 2 ≤ m, 1 ≤ h 1 ,h 2 ≤ w 1n,m,w10001r1,r2n,1c1,c2m,1h1,h2w,陷阱不在起点或终点,两个陷阱不同。


题解
记忆化搜索:可得 30% 的分数

#include <iostream>
#include <cstring>
using namespace std;

const int N = 310, MOD = 1e9 + 7;

int n, m, w;
int k, r1, c1, h1, r2, c2, h2;
int prime[N], g[N][N][N], f[N][N][N];

int dfs(int x, int y, int z)
{
	if(x == n && y == m && z == w) return 1;
	if(x == r1 && y == c1 && z == h1) return 0;
	if(x == r2 && y == c2 && z == h2) return 0;
	if(x < 1 || x > n || y < 1 || y > m || z < 1 || z > w) return 0;
	
	if(f[x][y][z] != -1) return f[x][y][z];
	
	int &v = f[x][y][z] = 0;
	for (int i = 0; i < k; i ++)
	{
		int step = prime[i];
		v = (v + dfs(x + step, y, z)) % MOD;
		v = (v + dfs(x, y + step, z)) % MOD;
		v = (v + dfs(x, y, z + step)) % MOD;
	}
	
	return f[x][y][z];
}

int main()
{
	cin >> n >> m >> w;
	cin >> r1 >> c1 >> h1 >> r2 >> c2 >> h2;
	
	for (int i = 2; i <= 310; i ++)
	{
		bool flag = true;
		for (int j = 2; j < i; j ++)
			if(i % j == 0)
			{
				flag = false;
				break;
			}
		if(flag) prime[k ++] = i;	
	}	
	
	memset(f, -1, sizeof f);
	cout << dfs(1, 1, 1) << endl;
	return 0;
} 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值