• 【题解】求和


    题目描述

            一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n。每个格子上都染了一种颜色colori(用[1,m]当中的一个整数表示),并且写了一个数字numberi。

    Failed to load picture

            定义一种特殊的三元组:(x,y,z),其中x,y,z都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:

            1、x,y,z都是整数,x<y<z,y-x=z-y;

            2、colorx=colorz;

            满足上述条件的三元组的分数规定为(x+z)×(numberx+numberz)。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以10007所得的余数即可。

    输入格式

            第一行是用一个空格隔开的两个正整数n和m,n代表纸带上格子的个数,m代表纸带上颜色的种类数。

            第二行有n个用空格隔开的正整数,第i个数字numberi代表纸带上编号为i的格子上面写的数字。

    输出格式

            共一行,一个整数,表示所求的纸带分数除以10007所得的余数。

    输入样例

    6 2

    5 5 3 2 2 2

    2 2 1 1 2 1

    输出样例

    82

     

    数据规模

            对于全部10组数据,1≤n≤100000,1≤m≤100000,1≤colori≤m,1≤numberi≤100000。

    题解

            其实这种题关键是要拿出笔来推一下,拆一拆并一并,整理完之后其实就很简单了。


            (提前声明,这里为了方便,用$a$表示$number$,用$b$表示$color$)

            观察题目,我们可以把条件一转换成$x$和$z$的奇偶性相同。

            又有条件二要求$b[x] = b[z]$。

            此时我们先设一个$x$,现在我们要求满足上面条件的有关$x$的三元组的和,又设这些三元组的数量为$cnt$,得到:

            $$egin{align*} sum_{i = 1}^{cnt}(x,  y_{i},  z_{i}) &= sum_{i = 1}^{cnt}(x + z_{i}) imes (a[x] + a[z_{i}]) \ &= sum_{i = 1}^{cnt} x imes a[x] + x imes a[z_{i}] + z_{i} imes a[x] + z_{i} imes a[z_{i}] end{align*}$$

            我们又设$sum = a[x] + sum_{i = 1}^{cnt} a[z_{i}]$,可以看出,对于$x$有关的部分也就是:

            $$ sum_{i = 1}^{cnt}x imes a[x] + x imes a[z_{i}] = x imes sum + x imes a[x] imes (cnt - 1) $$

            对于每一个$x$,我们都可以预处理出对应的$cnt$和$sum$,直接求解就行了。具体细节可以看下面的代码。

    #include <cstdio>
    
    #define MAX_N 1000000
    #define MAX_M 1000000
    #define MOD 10007
    
    using namespace std;
    
    int n, m;
    int a[MAX_N | 1];
    int b[MAX_N | 1];
    int c[MAX_M << 1 | 1];
    int s[MAX_M << 1 | 1];
    int ans;
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for(register int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
        }
        for(register int i = 1; i <= n; ++i)
        {
            scanf("%d", &b[i]);
            ++c[b[i] + m * (i & 1)];
            s[b[i] + m * (i & 1)] += a[i];
            s[b[i] + m * (i & 1)] %= MOD;
        }
        for(register int i = 1; i <= n; ++i)
        {
            ans += (long long)i * a[i] * (c[b[i] + m * (i & 1)] - 2) % MOD;
            ans += (long long)i * s[b[i] + m * (i & 1)] % MOD;
            ans %= MOD;
        }
        printf("%d", ans);
        return 0;
    }
    参考程序
  • 相关阅读:
    【翻译】JavaScript循环和作用域
    【js-xlsx和file-saver插件】前端导出数据到excel
    H5混合开发进阶
    一分钟搞定vue全局注册事件eventBus
    cordova+vue构建app进阶
    LayaBox进阶之UI管理器
    Layabox进阶之资源加载
    H5混合开发进阶之inspect调试
    认识json
    正则学习记录
  • 原文地址:https://www.cnblogs.com/kcn999/p/11195232.html
Copyright © 2020-2023  润新知