目录
题目描述
n 个人,每个人有一个编号 ai 。
定义对 a 的再编号为 a' ,满足 ai′=(∑j=1naj)−aia'_{i}=( \displaystyle \sum_{j=1}^{n} a_{j} )-a_{i}ai′=(j=1∑naj)−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;
}