博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
牛客练习赛25 C 再编号
阅读量:5323 次
发布时间:2019-06-14

本文共 1255 字,大约阅读时间需要 4 分钟。

解题思路

我们先来观察一下题目中给出的公式

$$a'_i=(\sum_{j=1}^na_j)-a_i$$

通过这个公式推一下经过再编号后的序列的总和,因为我们推出这个和之后可以进行下一次计算。

$$\sum_{i=1}^na'_i=\sum_{i=1}^n((\sum_{j=1}^na_j)-a_i)$$

变形一下

$$\sum_{i=1}^na'_i=n\times (\sum_{j=1}^na_j)-\sum_{i=1}^na_i$$

$$\sum_{i=1}^na'_i=(n-1)\times \sum_{i=1}^na_i$$

emmmm,这个结论貌似很有用的样子,我们可以通过上面的推导预处理处每一次变化后整个序列的总和。

在观察一下原来的序列,每一次再编号他们的每个数和第一个数的差的绝对值是不变的。并且在奇数次的变化后为$a_1-a_j$,偶数次变化后是$a_j-a_1$。

既然是这样子,那我们就可以再通过之前预处理的总和在处理出每一次改变后的第一个值。通过这个值我们可以$O(1)$的对每一个位置上的数值进行询问。

这样的话总时间复杂度是$O(t)$的

 

代码看这里

#include 
#include
#include
#include
#include
#include
#include
using namespace std;#define LL long long#define mod int(1e9+7)LL a[100010],n,m,sum[100100];LL ans[100001][2],num;int main(){ LL x,t; scanf("%lld%lld%lld",&n,&m,&a[1]); num=a[1]; for(int i=2;i<=n;i++) { scanf("%lld",&a[i]); num+=a[i]; sum[i]=a[1]-a[i]; } ans[0][1]=a[1]; for(int i=1;i<=100001;i++) { ans[i][1]=((num-a[1])+2*mod)%mod; a[1]=ans[i][1]; num=(num*(n-1))%mod; } for(int i=1;i<=m;i++) { scanf("%lld%lld",&x,&t); if(t%2!=0)printf("%lld\n",(ans[t][1]+sum[x]+mod)%mod); else printf("%lld\n",(ans[t][1]-sum[x]+mod)%mod); }}

 

转载于:https://www.cnblogs.com/bljfy/p/9532789.html

你可能感兴趣的文章
SOPC Builder中SystemID
查看>>
MySQL数据库备份工具mysqldump的使用(转)
查看>>
NTP服务器配置
查看>>
关于 linux 的 limit 的设置
查看>>
HDU(4528),BFS,2013腾讯编程马拉松初赛第五场(3月25日)
查看>>
vim中文帮助教程
查看>>
MySQL基础3
查看>>
RxJS & Angular
查看>>
面向对象(多异常的声明与处理)
查看>>
MTK笔记
查看>>
ERROR: duplicate key value violates unique constraint "xxx"
查看>>
激活office 365 的启动文件
查看>>
无法根据中文查找
查看>>
[简讯]phpMyAdmin项目已迁移至GitHub
查看>>
转载 python多重继承C3算法
查看>>
【题解】 bzoj1597: [Usaco2008 Mar]土地购买 (动态规划+斜率优化)
查看>>
css文本溢出显示省略号
查看>>
git安装和简单配置
查看>>
面向对象:反射,双下方法
查看>>
鼠标悬停提示文本消息最简单的做法
查看>>