bzoj3939 【USACO 2015 FEB GOLD 】cow hopscotch

Description
就像人类喜欢玩“跳房子”的游戏,农民约翰的奶牛已经发明了该游戏的一个变种自己玩。由于笨拙的动物体重近一吨打,牛跳房子几乎总是以灾难告终,但这是没有阻止奶牛几乎每天下午玩这个游戏。
游戏的矩阵共有R*C格(2 <= R <= 750,2 <= C <= 750),其中每一格是个正方形并被标记为一个整数K( 1 < = K <= R * C)。游戏是牛开始在左上角最后向右下角移动到的一个跳跃序列,牛从一个格子只能跳到在他的严格右下方(行列都要大于当前位置)与当前格子权值不同的格子上。请帮助奶牛计算不同可能的有效跳跃序列的数量。
Input
第一行三个整数 R, C, K.
以下R行,每行 C个整数.
Output
输出方案数,由于数太大,请对答案取模 1000000007.
Sample Input
4 4 4
1 1 1 1
1 3 2 1
1 2 4 1
1 1 1 1
Sample Output
5

正解:分治or线段树


对于列分治,每次分治时,先把≤mid的区间处理,再统计≤mid的答案,然后加入>mid的区间中,复杂度O(n*m log n)。

取模的话,%一波r_64大神。。


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define il inline
#define RG register
#define ll long long
#define rhl 1000000007
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

int a[760][760],vis[562510],n,m,k,T;
ll f[760][760],s[562510];

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void solve(RG int l,RG int r){
    if (l==r) return; RG int mid=(l+r)>>1;
    solve(l,mid); T++; RG ll sum=0;
    for (RG int i=2;i<=n;++i){
	for (RG int j=l;j<=mid;++j){
	    if (vis[a[i-1][j]]!=T) s[a[i-1][j]]=0,vis[a[i-1][j]]=T;
	    (sum+=f[i-1][j])%=rhl,(s[a[i-1][j]]+=f[i-1][j])%=rhl;
	}
	for (RG int j=mid+1;j<=r;++j){
	    if (vis[a[i][j]]!=T) s[a[i][j]]=0,vis[a[i][j]]=T;
	    (f[i][j]+=sum-s[a[i][j]]+rhl)%=rhl;
	}
    }
    solve(mid+1,r); return;
}

il void work(){
    n=gi(),m=gi(),k=gi(); f[1][1]=1;
    for (RG int i=1;i<=n;++i)
	for (RG int j=1;j<=m;++j) a[i][j]=gi();
    solve(1,m); printf("%lld\n",f[n][m]); return;
}

int main(){
    File("cowhouse");
    work();
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值