CodeChef FEB16 数组

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+xival[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

ap+b0%p

i1ab1%p

需要的就是 i1
然后递归处理(记忆化搜索),或者递推
这样求很多逆元时就会很快了,求逆元总复杂度不超过 O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值