您的位置:首页 > Web前端

CodeChef FEB16 数组

2016-09-23 12:23 176 查看
CodeChef FEB16 数组

Chef has an array A consisting of N integers (1-based indexing). He asks you to perform the following operation M times:

for i = 2 to N: Ai = Ai + Ai-1

Your task is to find the xth element of the array (i.e., Ax) after performing the above operation M times. As the answer could be large, please output it modulo 109 + 7.

Input

The first line of input contains an integer T denoting the number of test cases.

The first line of each test case contains three space-separated integers — N, x, and M — denoting the size of the array, index of the element you need to find, and the amount of times you need to repeat operation before finding the element, respectively. The second line contains N space-separated integers A1, A2, …, AN.

Output

For each test case, output a single line containing one integer: Ax modulo 109 + 7.

Constraints

1 ≤ T ≤ 10

1 ≤ x ≤ N ≤ 105

1 ≤ M ≤ 1018

1 ≤ Ai ≤ 1018

Subtasks

Subtask 1 (8 points):

1 ≤ x ≤ min{2, N}

Subtask 2 (24 points):

1 ≤ N * M ≤ 106

[Solution]

这题主要还是打表找规律:

举个例子:

输入:

3 3 3

1 2 3

输出:

15

模拟每一次操作,计算每个数对答案的贡献:

1       2       3
1       3       6
1       4       10
1       5       15
再接下去就是:
1       6       21
1       7       28


发现每一个数由左和上相加得到

所以也会很容易发现每个数对答案的贡献:

0       0       1
1       1       1
3       2       1
6       3       1
10       4       1


如果把它反过来写:

1       1       1

1       2       3

1       3       6

1       4       10


然后再斜过来:

1

1       1

1       2       1

1       3       3       1

1       4       6       4       1


结果发现这个玩意儿好像就是杨辉三角.
但是想到这里就想不下去了-_-||,日常爆炸

所以发现它是杨辉三角没什么用……

但是杨辉三角就是组合数啊 !!!!!!!!!!.

所以其实这道题也就没什么了,就是从 x for 到 1 每次把答案加上:

Cmm+x−i∗val[i]

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long longl;
const int P=1e9+7;

int F[100005];
int f(int x) {
int A=P/x,B=P%x;
return F[x]!=-1? F[x] : F[x]=((1LL*-A*f(B))%P+P)%P;
}

int solve(int n,int x,int m) {
int A[100005];
for (int i=1;i<=n;++i) {
longl x;
cin>>x;
x%=P;
A[i]=x;
}
int C=1;
int res=C*A[x];
for (int i=x-1;i>=1;--i) {
C=1LL*C*(m-1+x-i)%P*f(x-i)%P;
res=(res+C*A[i]%P)%P;
}
return res;
}

int main() {
memset(F,-1,sizeof(F));
F[1]=1;
int n,x;
longl m;
while (cin>>n>>x>>m) {
m%=P;
cout<<solve(n,x,m)<<endl;
}
return 0;
}


这里用了一个神奇的求逆元方法:

假设求i的逆元:

设a=i/p,b=i%p

a∗p+b≡0%p

i−1≡−a∗b−1%p

需要的就是i−1

然后递归处理(记忆化搜索),或者递推

这样求很多逆元时就会很快了,求逆元总复杂度不超过O(n)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CodeChef 数论