題目描述
n 個人,每個人有一個編號 ai 。
定義對 a 的再編號爲 a' ,滿足 。
現在有 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 ≤ 10^9
解題思路:給你n個數然後一個公式,然後求第t次變化後第x個人的值是多少?
我們就拿樣例來舉例
(0) 1 2 3 4
(1) 9 8 7 6
(2) 21 22 23 24
(3) 69 68 67 66
不管怎麼變 第i個位置的值減去第1個位置的值的絕對值始終沒有發生改變
(0) 1 2 3 4 sum0=10
(1) 9 8 7 6 sum1=30
(2) 21 22 23 24 sum2=90
(3) 69 68 67 66 sum3=270
sum[i]=sum[i-1]*(n-1)
那麼我們只需要求第t次的總和 和第t次第一個數的大小就行,這樣的話 其他數我只需要看對應關係就行。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=2e5+10;
const long long mod=1e9+7;
#define ll long long
int n,m;
ll sum[maxn],num[maxn],a[maxn],b[maxn];
int main(){
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[0]=(sum[0]+a[i])%mod;
b[i]=(mod+a[i]-a[1])%mod;
}
num[0]=a[1];sum[0]=(sum[0]+mod)%mod;
for(i=1;i<=100000;i++){
sum[i]=1LL*(n-1)*sum[i-1]%mod;
num[i]=(sum[i-1]-num[i-1]+mod)%mod;
}
while(m--){
int x,y;
scanf("%d%d",&x,&y);
ll ans;
if(y&1){
ans=(mod+num[y]-b[x])%mod;
}
else{
ans=(mod+num[y]+b[x])%mod;
}
printf("%lld\n",ans);
}
return 0;
}