再编号题解(前缀和,差分)

目录

题目描述

输入描述:

输出描述:

输入

输出

说明

备注:

思路:

代码:


题目描述

n 个人,每个人有一个编号 ai 。

定义对 a 的再编号为 a' ,满足 ai′=(∑j=1naj)−aia'_{i}=( \displaystyle \sum_{j=1}^{n} a_{j} )-a_{i}ai′​=(j=1∑n​aj​)−ai​ 。

现在有 m 次询问,每次给定 x,t ,表示询问经过 t 次再编号后第 x 个人的编号。

由于答案可能很大,所以对 109+7 取模。

输入描述:

第一行 2 个数 n,m ,表示人数和询问次数;

接下来一行 n 个数,表示 ai ;

接下来 m 行,每行 2 个数 x,t ,描述一次询问。

输出描述:

m 行,第 i 行 1 个数表示第 i 次询问的答案对 109+7 取模的结果。

示例1

输入

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

输出

1
22
6

说明

初始编号:1  2  3  4

1 次再编号后:9  8  7  6

2 次再编号后:21  22  23  24

备注:

n ≤ 100000 , m ≤ 10000 , t ≤ 100000 , 1 ≤ ai ≤ 109

思路:

1,模拟一下,发现sum[i]=(n-1)*sum[i-1],最新的和是旧和的n-1倍

2,a[i]与a[1]差值的绝对值恒定

代码:

#include<bits/stdc++.h>
using namespace std;//等差等比求和,或者(这题)各项差值的绝对值一定
#define int long long
const int mod = 1e9+7 , maxj = 1e5+100;
int32_t main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n,m;
    int a[maxj],sum[maxj],d[maxj],now[maxj];
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        sum[0]=(sum[0]+a[i])%mod;
        d[i]=(a[i]-a[1])%mod;
    }
    now[0]=a[1];//都从0开始
    for(int i=1;i<=100000;++i){
        sum[i]=(n-1)*sum[i-1]%mod;
        now[i]=(sum[i-1]-now[i-1]+mod)%mod;
    }
    while(m--){
        int ans=0;
        int x,y;
        cin>>x>>y;
        if(y&1){
            ans=(now[y]-d[x]+mod)%mod;//模后可能为负,要+mod
        }else{
            ans=(now[y]+d[x])%mod;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值