牛客練習賽25 C 再編號

題目描述

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章