牛客练习赛25 C 再编号
解题思路
我们先来观察一下题目中给出的公式
$$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 <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <queue> #include <vector> 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); } }
作者:Mystical-W
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可