0%

跳格子

有n*m的格子,并且是个跳格子的地方。每个格子有一个颜色c。现在你要从网格的左上角调到右下角,并且遵守以下规则:
设当前格子为(x,y)。
1)对于每次跳到的格子(tx,ty), tx>x, ty>y
2)对于每次跳到的格子(tx,ty), c[(tx,ty)]≠c[(x,y)]
问有多少种跳法。

输入描述:

第一行三个整数n,m,k,表示行和列以及颜色的范围[1,k]。
接下来n行,每行m个整数表示当前格子颜色。
对于100%的数据,n,m<=750, k<=n*m。

输出描述:

一个正整数s表示跳法数量。答案对10^9+7取模。

示例1
输入

4 4 4
1 1 1 1
1 3 2 1
1 2 4 1
1 1 1 1

输出

5

tiaogezi.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 755
#define P 1000000007
using namespace std;
int n,m,k;
int del[M*M];
int c[M][M],dp[M][M];
void CDQ(int L,int R){
if(L==R)return;
int mid=(L+R)>>1;
CDQ(L,mid);
int sum=0;
for(int j=2;j<=m;j++){
for(int k=L;k<=mid;k++){
sum=(sum+dp[k][j-1])%P;
del[c[k][j-1]]=(del[c[k][j-1]]+dp[k][j-1])%P;
}
for(int k=mid+1;k<=R;k++){
dp[k][j]=(dp[k][j]+sum)%P;
dp[k][j]=(dp[k][j]-del[c[k][j]]+P)%P;
}
}
for(int j=1;j<=m;j++)
for(int k=L;k<=mid;k++)
del[c[k][j]]=0;
CDQ(mid+1,R);
}
int main(){
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&c[i][j]);
dp[1][1]=1;
CDQ(1,n);
printf("%d\n",dp[n][m]);
return 0;
}