Loading

入阵曲

考场想到正解思路的一部分,还是太菜了。
最后把所有能骗的分都骗了,手动鄙视我自己。

考场上最后十分钟,我在推一维的情况,并且推出来了,但是跟题解不太一样,需要一个取模的循环指针来实现,这里就不放出来让大家嘲笑了。
然后我回宿舍的一晚上没想到如何扩展到二维(也许是一开始推的就有点怪?),反正我菜就完事了。

把所有的矩形都考虑是由若干行压成的一行和若干列构成的。
处理一行是\(O(n)\),一共有\(n^2/2\)行,复杂度擦边(我考场上以为\(n^3\)过不去)。

其实搞个一维前缀和就可以实现了。

code
#include <cstring>
#include <algorithm>
#include <cstdio>
#define mp make_pair
#define R register int
#define int long long
#define printf Ruusupuu = printf

int Ruusupuu ;

using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned long long G ;
typedef pair< int , int > PI ;
const int N = 4e2 + 10 ;
const int M = 1e6 + 10 ; 

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
	while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ '0' ) , ch = getchar() ;
	return fg ? -w : w ; 
}

int n , m , k , a [N][N] , q [N][N] , f [M] , ans ; 
int stk [N] , top ;

void sc(){
	n = read() , m = read() , k = read() ;
	for( R i = 1 ; i <= n ; i ++ )
		for( R j = 1 ; j <= m ; j ++ )
			a [i][j] = read() ;  
}

inline void solve( int st , int ed ){
	top = 0 , f [0] = 1 ; int val = 0 ;
	for( R i = 1 ; i <= m ; i ++ ){
		val = ( val + q [ed][i] - q [st - 1][i] ) % k ; 
		ans += f [val] , stk [++ top] = val , f [val] ++ ;	
//		printf( "%ld %ld %ld %ld %ld %ld %ld %ld\n" , st , q [st - 1][i] , ed , q [ed][i] , i , val , f [val] - 1 , ans ) ;		
	} while( top ) f [stk [top --]] = 0 ; 
//	for( R i = 0 ; i <= k ; i ++ ) printf( "%ld\n" , f [i] ) ;
} 

void work(){
	for( R i = 1 ; i <= m ; i ++ )
		for( R j = 1 ; j <= n ; j ++ )
			q [j][i] = q [j - 1][i] + a [j][i] ; 

	for( R i = 1 ; i <= n ; i ++ )
		for( R j = i ; j <= n ; j ++ )
			solve( i , j ) ;
		
	printf( "%lld\n" , ans ) ;
}

signed main(){	
	sc() ;
	work() ;
	return 0 ;
} 


posted @ 2021-06-27 19:18  Soresen  阅读(93)  评论(0)    收藏  举报