小a和uim之大逃離(luogu P1373 dp)
阿新 • • 發佈:2017-12-12
math block pac clu 偶數 char sdi span lag 。那麽狀態轉移方程就是:\[f[i][j][p][0]=f[i][j-1][p1][1]+f[i-1][j][p1][1]+(p1?0:1)\]\[f[i][j][p][1]=f[i][j-1][p2][0]+f[i-1][j][p2][0]\]
小a和uim之大逃離(luogu P1373 dp)
給你一個n*m的矩陣,其中元素的值在1~k內。限制只能往下和往右走,問從任意點出發,到任意點結束,且經過了偶數個元素的合法路徑有多少個。在此題中,定義在一條路徑中,第奇數個元素之和為X,第偶數個元素之和為Y。X+Y同模k+1的路徑是合法路徑。答案模1e9+7。n,m<=800,1<=k<=15。
狀態是\(f[i][j][h][0/1]\),表示第i行第j列的元素,奇數元素和X-偶數元素和Y差為h,當前在路徑中是第奇數個點或第偶數個點的方案數。
設\(p1=(p-a[j]+k+1)\% (k+1)\),\(p2=(p+a[j])\%(k+1)\)
狀壓一下即可。
#include <cctype>
#include <cstdio>
#include <cstring>
using namespace std;
const int mod=1e9+7;
const int maxn=805, maxk=20;
typedef int ia3[maxn][maxk][2 ];
int n, m, k, ans, a[maxn];
ia3 fnow, fpre;
void getint(int &x){
char ch; int flag=1; x=0;
for (ch=getchar(); !isdigit(ch); ch=getchar())
if (ch=='-') flag=-1;
for (x=ch-48; ch=getchar(), isdigit(ch);)
x=x*10+ch-48;
x*=flag;
}
int main(){
scanf(" %d%d%d", &n, &m, &k);
int p1, p2;
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j){
getint(a[j]);
for (int p=0; p<=k; ++p){
p1=(p-a[j]+k+1)%(k+1); //這一步若小A走
p2=(p+a[j])%(k+1); //這一步若uim走
fnow[j][p][0]=(fnow[j-1][p1][1]
+fpre[j][p1][1]+(p1?0:1))%mod;
fnow[j][p][1]=(fnow[j-1][p2][0]
+fpre[j][p2][0])%mod;
if (p==0) ans=(ans+fnow[j][p][1])%mod;
}
memcpy(fpre[j], fnow[j], sizeof(fnow[j]));
}
printf("%d\n", ans);
return 0;
}
小a和uim之大逃離(luogu P1373 dp)