首页 > 其他 > 详细

NOIP 2015PJ T3求和

时间:2020-04-28 09:07:51      阅读:62      评论:0      收藏:0      [点我收藏+]

大概是NOIP 2015 T3求和题解(

 

 

 

那么首先发一下题目

 

 

 

题目描述

 

 

                               技术分享图片

 

 

 技术分享图片

 

 

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

         

      1.xyz是整数,x<y<z,y-x=z-y

      2.colorx=colorz

 

技术分享图片

 

 

 

输入格式

技术分享图片

 

 

输出格式

技术分享图片

 

 

 

输入#1

6 2

5 5 3 2 2 2 

2 2 1 1 2 1

 

输出#1

82

 

输入#2

15 4 

5 10 8 2 2 2 9 9 7 7 5 6 4 2 4

2 2 3 3 4 3 3 2 4 4 4 4 1 1 1

 

输出#2

1388

 

 

 

那么下面开始分析环节:

 

一   分析题目

 

题目很好懂

 

1.首先理解三元组要求

    1.xyz是整数,x<y<z,y-x=z-y

      2.colorx=colorz

 

2.找到三元组后的处理

 

即是累加(x+z)  x (number_x+number_z)

 

 

 

二 思考初步解题策略并观察数据范围

 

首先一步变形:y-x=z-y可以变成  2y=x+z

 

数学好的小伙伴可能会发现这是个等差中项,嗯不过和这个题没啥关系(

 

 

 

第一想法,既然要满足三元组要求的话,直接枚举x,y,z不就好了嘛。最外层枚举y点,再在内层循环寻找x点与z点,然后再特判颜色以及是否满足2y=x+z,找到后累加即可

 

复杂度O(n^3)得分20

 

 

 

第二想法 看了看数据范围后发现O(n^3)的算法太扯了,考虑优化。我们发现,当2y=x+z时,两边都时mod一个2后,可以知道x+zΞ0(mod2)(翻译成计算机语言就是(x+z)%2==0)这样就是一个满足条件的三元组。有些同学这里可能会疑惑,认为这样不够严谨,其实这样是合理的。因为在满足x<y<z时,若x z确定,那么y必定有存在性。而且我们对于求和的处理中也没有牵扯y的计算,所以直接枚举x z,然后特判一下同奇偶性以及颜色,再处理求和就可以了。

 

复杂度O(n^2)得分 40

 

 

 

三 最终正解想法以及推理流程

 

其实AC前两题加上O(n^2)的算法后已经达到了240的高分,那么看到这里的一定是力求AK的大佬选手了。

 

在介绍完O(n^2)的算法后发现还是欠优异,此时我们注意数据范围

 

技术分享图片

 

技术分享图片

 

n可以开到10万,数据毒以及优化难想到是这个题的最大难点(毕竟是个绿题起码还是要点面子的嘛)

 

我们有了第二想法的关于奇偶性判定这一思路后,考虑O(n)算法。

 

我们发现当有 A1 A2 A3.....An这n个数满足互相形成三元组后,这里注意是“互相“,也就是A1A2 A2A3 A1A3....

 

不妨考虑这几个数处理后加和的值

 

这里是公式以及证明:

 

技术分享图片

 

 

 

 得出如此结论后就非常简单了,那么我们只要找出符合奇偶性,以及符合同颜色性质的数然后统一套到这个公式里求和一波就可以了。

 

 

 

 

 

 四  预处理的技巧以及完美代码的呈现

 

显然,我们要做一波预处理。

 

这里呢我的数组sum[2][1000000]前面的维度判断奇偶性质,后面的维度呢就是判断颜色性质,这个数组用来存储Σnumber[i]。

 

然后我又定义了个vis[2][100000]数组,作用是在此奇偶性以及颜色性质判断下,元素的个数。

 

预处理代码如下

 

技术分享图片
技术分享图片
    for(int i=1;i<=n;i++)
    {
        sum[i%2][color[i]]+=number[i];
        sum[i%2][color[i]]%=Mod;
        vis[i%2][color[i]]++;
    }
技术分享图片
技术分享图片

 

最后根据我们前面的公式推理得出最终的处理求和代码

 

    for(int i=1;i<=n;i++)
{
    ans+=((i*(vis[i%2][color[i]]-2)*number[i])%Mod+(sum[i%2][color[i]]*i))%Mod;
    ans%=Mod;
}

 

这样,这个题基本就写完了,剩下的工作就是读入了。

 

 

 

完整代码呈现:

 

技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define Mod 10007
#define N 100007
long long ans,sum[2][N],color[N],number[N];
int vis[2][N];
using namespace std;
int main()
{
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>number[i];
        number[i]%=Mod;
    }
    for(int j=1;j<=n;j++)
    {
        cin>>color[j];
    }
    for(int i=1;i<=n;i++)
    {
        sum[i%2][color[i]]+=number[i];
        sum[i%2][color[i]]%=Mod;
        vis[i%2][color[i]]++;
    }
    
    for(int i=1;i<=n;i++)
{
    ans+=((i*(vis[i%2][color[i]]-2)*number[i])%Mod+(sum[i%2][color[i]]*i))%Mod;
    ans%=Mod;
}

cout<<ans;
return 0;    
 } 
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片

 

 

 

 

 

五 个人的看法已经一些其他的话(

 

这个题我想花了10min,毕竟因式分解啥的对于我这种数学竞赛生来说本身不是难事,码的话花了20min,基本在于思考预处理问题上了。这个题我认为的巧妙之处不在于因式分解以及公式推理,在于预处理的巧妙运用以及一次次考虑优化的过程。从O(n^3)到O(n)的一次次思维跃进。解决一个题不是目的,学会了这样的优化思维以及预处理的技巧,我想,这才是这个题的真正意义。

 

 

 

然后呢对于历城二中信息奥赛队中较多队员AC了这道题,其中还有位五年级的同学并且是此次测试的Rank1。

 

我这一初三老头还那么菜......(羞愧脸)五年级就已熟练运用因式分解以及求和符号属实强壮。最后呢祝愿历城二中信息队的队员携手并进越来越强,同时也祝广大oier能在NOIP2020中取得满意的成绩。

 

技术分享图片

 

 

 

 

 

如果对您有帮助的话可以给个赞嘛qwq

 

 

 

 

 

 

 

 

 

 

NOIP 2015PJ T3求和

原文:https://www.cnblogs.com/gclqwq/p/12791297.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!