入阵曲
考场想到正解思路的一部分,还是太菜了。
最后把所有能骗的分都骗了,手动鄙视我自己。
考场上最后十分钟,我在推一维的情况,并且推出来了,但是跟题解不太一样,需要一个取模的循环指针来实现,这里就不放出来让大家嘲笑了。
然后我回宿舍的一晚上没想到如何扩展到二维(也许是一开始推的就有点怪?),反正我菜就完事了。
把所有的矩形都考虑是由若干行压成的一行和若干列构成的。
处理一行是\(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 ;
}
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号