原题大意
n个正整数排成一行,每相邻两个数进行加或减操作:第一第二个数相加,第二第三个数相减,第三第四个数相加,第四第五个数相减……,得到的结果排成第二行,然后继续这样的操作,并且初始的前两个数是加还是减,与上一行最后两个数的操作符相反,问最后得到的结果是多少?
算法分析
考虑最简版本每个ai对最终式子的贡献,可以令ai的系数为1,其余为0,类似0,0,0…1…0,0,0,同时暂且不考虑减法,可以得出每个ai的贡献为C(n-1,k-1) ,然后通过下面这个过程,可以看出最终的式子,是两个奇偶序列和(最简版本),相加或做差得到的,n mod 4 = 2时相加,n mod 4 = 0时做差。(如果n是奇数,那么先暴力进行第一次变换使得n成为偶数)
程序代码
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const ll maxn = 200000+5;
ll fac[maxn], inv[maxn];//fac[i] 保存阶乘,inv[i] 保存fac[i]的逆元
ll a[maxn];
ll ans;
int n;
void add(ll &a, ll b){
a += b;
if(a >= mod) a -= mod;
}
//快速幂
ll pow_mod(ll a, ll p){
ll ans = 1;
while(p){
if(p & 1) ans = ans * a % mod;
a = a * a % mod;
p >>= 1;
}
return ans;
}
//组合计算公式
ll C(int n, int k){
return (fac[n] * inv[k] % mod )* inv[n-k] % mod;
}
int main(){
//freopen("input.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
fac[0] = 1;
for(int i = 1; i < maxn; i++) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = pow_mod(fac[maxn-1],mod-2);
for(int i = maxn - 2; i >=0; i--) inv[i] = inv[i+1] * (i+1) % mod;
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
if(n&1){
if(n == 1) {cout << a[1] << endl; return 0;}
int sign = 1;
for(int i = 1; i < n; i++){
a[i] = (a[i]+sign*a[i+1] + mod) %mod;
sign*=-1;
}
n--;
}
ll sum1 = 0LL, sum2 = 0LL;
for(int i = 1; i <= n; i++){
if(i&1) add(sum1, C(n/2-1, i/2) * a[i]%mod);
else add(sum2, C(n/2-1, i/2-1) * a[i]%mod);
}
if(n%4 != 0) cout << (sum1 + sum2) % mod << endl;
else cout << (sum1 - sum2 + mod) % mod << endl;
return 0;
}