题目链接: 【hrbust】2298 Diamond
枚举斜率算贡献。 n2logn 预处理, O(1) 查询。
PS:一开始写了 n2logn 每组,然后 TLE 了,思考了一下发现可以先预处理,然后每组 O(N2) ,结果又 TLE 了……然后再思考了一下发现可以 O(N) 询问,就是代码量瞬间长了一些……总体来说还是比较简单的……最后我将唯一一个 O(N) 的部分优化到了 O(1) ,即每组 O(1) 查询。
#include <bits/stdc++.h>
using namespace std ;
typedef long long LL ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 1005 ;
int n , m ;
int cnt[MAXN][MAXN] ;
LL sum1[MAXN][MAXN] , sum2[MAXN][MAXN] ;
int R[MAXN][MAXN] , C[MAXN][MAXN] ;
LL odd[MAXN] , even[MAXN] ;
void solve () {
if ( n > m ) swap ( n , m ) ;
LL ans = 1LL * ( n * m + n + m ) * sum1[n][m] + sum2[n][m] ;
ans -= 1LL * n * R[n][m] + 1LL * m * C[n][m] ;
if ( n % 2 ) {
if ( m % 2 ) ans += even[n - 1] * even[m - 1] ;
else ans += even[n - 1] * odd[m - 1] ;
} else {
if ( m % 2 ) ans += odd[n - 1] * even[m - 1] ;
else ans += odd[n - 1] * odd[m - 1] ;
}
ans += 1LL * n * ( n * m + n + m ) ;
ans -= 1LL * ( n + m ) * ( 1 + n ) * n / 2 ;
ans += 1LL * ( n - 1 ) * n * ( 2 * n - 1 ) / 6 ;
printf ( "%lld\n" , ans ) ;
}
int main () {
for ( int i = 1 ; i < MAXN ; ++ i ) {
for ( int j = 1 ; j < MAXN ; ++ j ) {
int g = __gcd ( i , j ) ;
for ( int k = 1 ; ; ++ k ) {
int x = k * j / g , y = k * i / g ;
if ( x >= MAXN || y >= MAXN ) break ;
if ( i == j && x == i ) continue ;
if ( x % 2 == i % 2 && y % 2 == j % 2 ) {
cnt[max ( x , i )][max ( y , j )] ++ ;
}
}
}
}
for ( int i = 1 ; i < MAXN ; ++ i ) {
for ( int j = 1 ; j < MAXN ; ++ j ) {
C[i][j] = C[i - 1][j] + cnt[i][j] * i ;
R[i][j] = R[i][j - 1] + cnt[i][j] * j ;
sum1[i][j] = sum1[i][j - 1] + cnt[i][j] ;
sum2[i][j] = sum2[i][j - 1] + 1LL * cnt[i][j] * ( i - 1 ) * ( j - 1 ) ;
}
}
for ( int i = 1 ; i < MAXN ; ++ i ) {
for ( int j = 1 ; j < MAXN ; ++ j ) {
R[i][j] += R[i - 1][j] ;
C[i][j] += C[i][j - 1] ;
sum1[i][j] += sum1[i - 1][j] ;
sum2[i][j] += sum2[i - 1][j] ;
}
}
for ( int i = 1 ; i < MAXN ; ++ i ) {
odd[i] = odd[i - 1] ;
even[i] = even[i - 1] ;
if ( i % 2 ) odd[i] += i ;
else even[i] += i ;
}
while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
return 0 ;
}
429

被折叠的 条评论
为什么被折叠?



