P2671 [NOIP2015 普及组] 求和

题目链接:P2671 [NOIP2015 普及组] 求和P2671 [NOIP2015 普及组] 求和https://www.luogu.com.cn/problem/P2671

 

题目分析(结合题解整理出我能看懂的)

20分做法

看完这题,第一想法当然是无脑暴力啦...直接枚举x,y,z,看是否满足条件即可。算法复杂度为O(N^3)O(N3)。[代码就算了]

这样就可得20分了。当然,如果你想用更高级的算法不开long long也是可以的。

40分做法

可以直接枚举x,z的值,通过条件(1)求出y。再看是否满足条件。算法复杂度为O(N^2)

40~50分做法

仍然是枚举x,z的值,但可以先分析x+z=2*y的奇偶性,因为xyz是整数,因此2y是2的倍数,因此x,z必然都为偶数或奇数,因此可以分奇偶性进行枚举,此时这个三元组即可不考虑y值的大小,即为当(i%2==1)枚举前面奇数序列相同的颜色进行算分数即可,算法复杂度为O(N^2/2)。

100分做法

通过上面的观察我们可以发现倒回去算前面的分数可能比较浪费时间,因此,我们采用数学的方法来优化
P2671 [NOIP2015 普及组] 求和

P2671 [NOIP2015 普及组] 求和

 P2671 [NOIP2015 普及组] 求和

P2671 [NOIP2015 普及组] 求和

 P2671 [NOIP2015 普及组] 求和

P2671 [NOIP2015 普及组] 求和

 

AC CODE

#include <cstdio>

const int N = 100000;
const int M = 10007;
int n, m;
int sum[N + 1][2], nt[N + 1][2];
int color[N + 1], number[N + 1];
long long ans = 0;

int main()
{
    scanf(" %d %d", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &number[i]);
        number[i] %= M;
    }
    for(int i = 1; i <= n; i++) {
        scanf("%d", &color[i]);
        int c = color[i];
        int g = i % 2;
        nt[c][g]++;
        sum[c][g] += number[i];
        sum[c][g] %= M;
    }
    for(int i = 1; i <= n; i++) {
        int c = color[i];
        int g = i % 2;
        ans += i % M * ((sum[c][g] + (nt[c][g] - 2) % M * number[i] + M) % M);
        ans %= M;
    }
    printf("%lld", ans);
    return 0;
}

侵删 

上一篇:P2615 [NOIP2015 提高组] 神奇的幻方


下一篇:[模板]有向图最小环 & 洛谷P2661 [NOIP2015 提高组] 信息传递