【hrbust】2298 Diamond 【数学+暴力】

来源:互联网 发布:黑客网站攻击软件 编辑:程序博客网 时间:2024/06/04 23:18

题目链接: 【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 ;}
0 0
原创粉丝点击