• Luogu 2671 求和 NOIP2015T3


    题目链接

    题解

    20pts

    $O(n^3)$枚举$x,y,z$,根据题目要求判断

    40pts

    $O(n^2)$枚举$x,z$,需要满足$x,z$奇偶相同

    20~40pts的代码我都没有写过...就不贴了

    70~90pts

    尝试对40pts的暴力进行优化

    题目对三元组的两个限制我们在40pts的时候已经用来优化过了,还有一个限制是颜色相同

    我们可以以颜色为关键字对数组进行排序,对每个数算答案的时候,只需要枚举相同颜色的这一段即可(因为三元组要求有序,所以要从$x+2$开始枚举)

    这样的复杂度是$O(n*cnt_{col})$(这里的$cnt_{col}$为出现次数最多的颜色的出现次数)

    使用$scanf$将会得到70pts

    使用快读或$scanf+O2$将会得到80pts

    使用快读+$O2$将会得到90pts

    ($fread$在这里的效果和快读是差不多的,因为数只有$1e5$个)

    #include <bits/stdc++.h>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    
    namespace io {
    
        #define in(a) a=read()
        #define out(a) write(a)
        #define outn(a) out(a),putchar('
    ')
    
        #define I_int int
        inline I_int read() {
            I_int x = 0 , f = 1 ; char c = getchar() ;
            while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
            while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
            return x * f ;
        }
        char F[ 200 ] ;
        inline void write( I_int x ) {
            I_int tmp = x > 0 ? x : -x ;
            if( x < 0 ) putchar( '-' ) ;
            int cnt = 0 ;
            while( tmp > 0 ) {
                F[ cnt ++ ] = tmp % 10 + '0' ;
                tmp /= 10 ;
            }
            while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
        }
        #undef I_int
    
    }
    using namespace io ;
    
    using namespace std ;
    
    #define N 100010
    const int mod = 10007 ;
    
    int n = read() , m = read() ;
    struct node {
        int col , val , id ;
    } a[ N ] ;
    
    bool cmp( node a , node b ) {
        return a.col < b.col ;
    }
    
    int main() {
        for( int i = 1 ; i <= n ; i ++ ) a[ i ].val = read() , a[ i ].id = i ;
        for( int i = 1 ; i <= n ; i ++ ) a[ i ].col = read() ;
        sort( a + 1 , a + n + 1 , cmp ) ;
        int cur = 0 ;
        ll ans = 0 ;
        for( int i = 1 ; i <= n ; i ++ ) {
            ll sum = 0 ;
            for( cur = i + 1 ; a[ i ].col == a[ cur ].col && cur <= n ; cur ++ ) {
                if( ( a[ i ].id + a[ cur ].id ) % 2 == 0 ) 
                    sum = ( sum + ( 1ll * ( a[ i ].id + a[ cur ].id ) % mod * 1ll * ( a[ i ].val + a[ cur ].val ) % mod ) % mod  ) % mod ;
            } 
            ans = ( ans + sum ) % mod ;
        }
        printf( "%lld
    " , ( ans + mod ) % mod ) ;
        return 0 ;
    }

    100pts

    考虑使用数学方法优化以上做法

    我们现在有什么条件呢,列举一下

    1.$x$和$z$的奇偶性相同且颜色相同

    2.求和公式为$(x+z)(num_x+num_z)$

    从求和公式入手,把括号拆掉,式子变成$x*num_x+x*num_z+z*num_x+z*num_z$

    设$x1,x2,x3$的奇偶性相同且颜色相同(那么他们组成的二元组就等同于符合条件的三元组)

    考虑$x1$对答案的贡献:

    对于$(x1,x2)$,$x1$的贡献为$x1*num_{x1}+x1*num_{x2}$

    对于$(x1,x3)$,$x1$的贡献为$x1*num_{x1}+x1*num_{x3}$

    那么$x_1$对答案的贡献就是

    $x1*(num_{x2}+num_{x3})+2*x1*num_{x1}$

    然后多加入一个数$x4$也可以得到类似的贡献(多代几个也就看出来规律了)

    推广到$x_n$结论也是一样的

    结论:

    设$s=sum num_{xi}$(这里的$xi$均满足条件1)$cnt=cnt_{col}$,$cnt_{col}$为当前颜色奇偶相同的数的个数

    则$xi$对答案的贡献为$xi*(s-num_{xi})+(cnt-1)*xi*num_{xi}$($cnt$要$-1$,因为$xi$不能和自己组成二元组)

    所以将$s$和$cnt$统计出来就行了,注意要分奇偶统计

    复杂度$O(n)$

    #include <bits/stdc++.h>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    #define int long long
    
    namespace io {
    
        #define in(a) a=read()
        #define out(a) write(a)
        #define outn(a) out(a),putchar('
    ')
    
        #define I_int int
        inline I_int read() {
            I_int x = 0 , f = 1 ; char c = getchar() ;
            while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
            while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
            return x * f ;
        }
        char F[ 200 ] ;
        inline void write( I_int x ) {
            if( x == 0 ) { putchar( '0' ) ; return ; }
            I_int tmp = x > 0 ? x : -x ;
            if( x < 0 ) putchar( '-' ) ;
            int cnt = 0 ;
            while( tmp > 0 ) {
                F[ cnt ++ ] = tmp % 10 + '0' ;
                tmp /= 10 ;
            }
            while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
        }
        #undef I_int
    
    }
    using namespace io ;
    
    using namespace std ;
    
    #define N 100010
    const int mod = 10007 ;
    
    int n , m ;
    struct node {
        int col , val ;
    } a[ N ] ;
    int cnt[ N ][ 2 ] , sum[ N ][ 2 ] ;
    
    signed main() {
        n = read() , m = read() ;
        for( int i = 1 ; i <= n ; i ++ ) a[ i ].val = read() ;
        for( int i = 1 ; i <= n ; i ++ ) a[ i ].col = read() ;
        for( int i = 1 ; i <= n ; i ++ ) {
            cnt[ a[ i ].col ][ i&1 ] ++ ;
            sum[ a[ i ].col ][ i&1 ] = ( sum[ a[ i ].col ][ i&1 ] + a[ i ].val ) % mod ;
        }
        ll ans = 0 ;
        for( int i = 1 ; i <= n ; i ++ ) {
            ll num = cnt[ a[ i ].col ][ i&1 ] , s = sum[ a[ i ].col ][ i&1 ] ;
            ans = ( ans + ( i*(s-a[i].val) + (num-1)*a[i].val*i ) % mod ) % mod ;
        }
        printf( "%lld
    " , ans % mod ) ;
        return 0 ;
    }
  • 相关阅读:
    字符编码相关
    函数之形参与实参
    文件操作模式
    函数对象,名称空间,作用域,和闭包
    吴裕雄天生自然SPRINGBOOT开发实战处理'spring.datasource.url' is not specified and no embedded datasource could be autoconfigured
    吴裕雄天生自然SPRINGBOOT开发实战处理XXXX that could not be found.
    吴裕雄天生自然SPRINGBOOT开发实战SpringBoot HTML表单登录
    吴裕雄天生自然SPRINGBOOT开发实战SpringBoot REST示例
    吴裕雄天生自然SpringBoot开发实战学习笔记处理 Could not write metadata for '/Servers'.metadata\.plugins\org.eclipse.core.resources\.projects\Servers\.markers.snap (系统找不到指定的路径。)
    吴裕雄天生自然SPRINGBOOT开发实战SpringBoot Tomcat部署
  • 原文地址:https://www.cnblogs.com/henry-1202/p/9926290.html
Copyright © 2020-2023  润新知