A B C 265 E − W a r p ABC 265E\!-\!W\!arp ABC265E−Warp
题目
Takahashi is at the origin of a two-dimensional plane.
Takahashi will repeat teleporting N \!N\! N times. In each teleportation, he makes one of the following moves:
- Move from the current coordinates ( x , y ) \!(\!x\!,\!y\!)\! (x,y) to ( x + A , y + B ) \!(\!x\!+\!A\!,\!y\!+\!B\!) (x+A,y+B)
- Move from the current coordinates ( x , y ) \!(\!x\!,\!y\!)\! (x,y) to ( x + C , y + D ) \!(\!x\!+\!C\!,\!y\!+\!D\!) (x+C,y+D)
- Move from the current coordinates ( x , y ) \!(\!x\!,\!y\!)\! (x,y) to ( x + E , y + F ) \!(\!x\!+\!E\!,\!y\!+\!F\!) (x+E,y+F)
There are obstacles on M \!M\! M points ( X 1 , Y 2 ) , … , ( X M , Y M ) \!(\!X_{1}\!,\!Y_{2}\!)\!,…,\!(\!X_{M}\!,\!Y_{M}\!)\! (X1,Y2),…,(XM,YM) on the plane; he cannot teleport to these coordinates.
How many paths are there resulting from the N teleportations?
Find the count modulo 998244353 998244353 998244353.
题目大意
一共有 N N N次移动次数
每次移动可以选择
从 ( x , y ) (\!x\!,\!y\!) (x,y)移动到 ( x + A , y + B ) (x\!+\!A,y\!+\!B) (x+A,y+B)或 ( x + C , y + D ) (x\!+\!C,y\!+\!D) (x+C,y+D)或 ( x + E , y + F ) (x\!+\!E,y\!+\!F) (x+E,y+F)
起始位置位于 ( 0 , 0 ) \!(\!0\!,\!0\!) (0,0)
有 M M M个地方无法走,分别是 ( X 1 , Y 2 ) , … , ( X M , Y M ) (\!X_{1}\!,\!Y_{2}\!),…,\!(\!X_{M}\!,\!Y_{M}\!) (X1,Y2),…,(XM,YM)
问有多少种移动 N \!N\! N次的不同方案,答案对 998244353 998244353 998244353取模
数据范围
- 1 ≤ N ≤ 300 1\!≤\!N\!≤\!300 1≤N≤300
- 0 ≤ M ≤ 10 0\!≤\!M\!≤\!10 0≤M≤10
- − 1 0 9 ≤ A , B , C , D , E , F ≤ 1 0 9 -10^9\!≤\!A,\!B,\!C,\!D,\!E,\!F\!≤\!10^9 −109≤A,B,C,D,E,F≤109
- 保证 ( A , B ) , ( C , D ) , ( E , F ) (\!A\!,\!B\!)\!,\!(\!C\!,\!D\!)\!,\!(\!E\!,\!F\!) (A,B),(C,D),(E,F)互不相同
- − 1 0 9 ≤ x i , y i ≤ 1 0 9 -10^9\!≤\!x_{i}\!,\!y_{i}\!≤\!10^9 −109≤xi,yi≤109
- 保证所有输入都为整数
读入格式
N N N M M M
A A A B B B C C C D D D E E E F F F
x
1
x_{1}
x1
y
1
y_{1}
y1
…
x M x_{M} xM y M y_{M} yM
内存和时间限制
- 时间限制 : 3 s :3s :3s
- 空间限制 : 1024 M B :1024M\!B :1024MB
分析
设三种移动方式分别为一,二,三,移动次数分别为 i i i, j j j, k k k
我们可以发现,由于初始坐标为 ( 0 , 0 ) (0,0) (0,0),因此,当前步数所处的点的位置可以用 i i i, j j j, k k k来表示
即 ( i × a + j × c + k × e , i × b + j × d + k × f ) (i\!\times\!a\!+\!j\!\times\!c\!+\!k\!\times\! e,i\!\times\!b\!+\!j\!\times\!d\!+\!k\!\times\!f) (i×a+j×c+k×e,i×b+j×d+k×f)
初步想法为四维 D P DP DP,即 f [ t e m p ] [ i ] [ j ] [ k ] f[temp][i][j][k] f[temp][i][j][k]表示前temp步,移法一走了 i i i次,移法二走了 j j j次,移法三走了 k k k次
因为 N N N的最大值为 300 300 300,开四维数组 N 4 N^4 N4会超内存
我们考虑一下类似于 N O I P 2008 N\!O\!I\!P2008 NOIP2008传纸条的优化思路(没做过的点这里)
显然 t e m p = i + j + k temp\!=\!i\!+\!j\!+\!k temp=i+j+k,那么我们便可以只设置一个三维数组,为 f [ t e m p ] [ i ] [ j ] f[temp][i][j] f[temp][i][j],其中 k k k可以通过 t e m p − i − j temp\!-\!i\!-\!j temp−i−j算出
由于本题只让求方案数
因此我们本次的方案数就等于上次走移法一的方案数 + + +上次走移法二的方案数 + + +上一次走移法三的方案数
由此,我们可以得到一个 D P D\!P DP式子:
f [ t e m p ] [ i ] [ j ] = ( f [ t e m p − 1 ] [ i ] [ j ] + f [ t e m p − 1 ] [ i − 1 ] [ j ] + f [ t e m p − 1 ] [ i ] [ j − 1 ] ) \boxed{f[temp][i][j]=(f[temp-1][i][j]+f[temp-1][i-1][j]+f[temp-1][i][j-1])} f[temp][i][j]=(f[temp−1][i][j]+f[temp−1][i−1][j]+f[temp−1][i][j−1])
显然, D P D\!P DP的数组为 f [ 0 ] [ 0 ] [ 0 ] = 1 f[0][0][0]\!=\!1 f[0][0][0]=1
我们分别枚举 t e m p , i , j temp,i,j temp,i,j,三重循环即可计算出答案
得到 D P D\!P DP式子后,我们再去思考如何判断这个位置能不能走,一个很显然的想法就是用 m a p map map进行判断
即
map<pair<int,int>,bool> fl;
然后对于每一个 x i , y i x_i,y_i xi,yi,我们进行如下操作
fl.insert(make_pair(make_pair(x,y),1));
枚举 t e m p , i , j temp,i,j temp,i,j时,只需判断移法一走 i i i步,移法二走 j j j步,移法三走 k k k步所到达的点是否在 m a p map map数组中即可
所以代码总时间复杂度为 O ( N 3 l o g M ) O(N^3logM) O(N3logM)
代码实现
本人蒟蒻,代码仅供参考
#include<bits/stdc++.h>
#define mod 998244353//注意要取模(分析里没有说)
#define PD(i,j,k) make_pair(i*a+j*c+k*e,i*b+j*d+k*f)//计算当前的位置
using namespace std;
int n,m,a,b,c,d,e,f,x,y,dp[306][305][305],ans;
map<pair<int,int>,bool> fl;
int main()
{
scanf("%d %d %d %d %d %d %d %d",&n,&m,&a,&b,&c,&d,&e,&f);
for(int i=0;i<m;++i)
scanf("%d %d",&x,&y),fl.insert(make_pair(make_pair(x,y),1));//将(x,y)添加进map数组
dp[0][0][0]=1;//初值设定
for(int temp=1;temp<=n;++temp)
for(int i=0;i<=temp;++i)
for(int j=0,k=temp-i-j;j+i<=temp;++j,--k)
{
if(fl.find(PD(i,j,k))!=fl.end())//判断是否能走
continue;
dp[temp][i][j]=((dp[temp-1][i][j]+dp[temp-1][i-1][j])%mod+dp[temp-1][i][j-1])%mod;//计算当前DP值
if(temp==n)
ans=(ans+dp[temp][i][j])%mod;//统计答案
}
printf("%d",ans);
return 0;
}