正题
题目链接:https://ac.nowcoder.com/acm/contest/20108/B
题目大意
给出一个长度为nnn的序列aaa,每次
- 如果nnn是偶数,则对于所有的i<ni<ni<n令新的ai′=ai′+ai+1′a'_i=a'_i+a'_{i+1}ai′=ai′+ai+1′
- 如果nnn是奇数,则对于所有的i<ni<ni<n令新的ai′=ai′−ai+1′a'_i=a'_i-a'_{i+1}ai′=ai′−ai+1′
1≤n≤105,1≤ai≤1091\leq n\leq 10^5,1\leq a_i\leq 10^91≤n≤105,1≤ai≤109
解题思路
对于一个位置它操作kkk次之后肯定可以用后面的若干个数表示,设多项式fk(x)=∑i=0∞bixif_k(x)=\sum_{i=0}^{\infty }b_ix^ifk(x)=∑i=0∞bixi有ap′=∑i=0nbi×ap+ia'_{p}=\sum_{i=0}^nb_i\times a_{p+i}ap′=∑i=0nbi×ap+i。
那么对于这个多项式如果nnn是奇数那么有fk(x)=fk−1(x)×(1+x)f_k(x)=f_{k-1}(x)\times (1+x)fk(x)=fk−1(x)×(1+x),否则fk(x)=fk−1(x)×(1−x)f_k(x)=f_{k-1}(x)\times (1-x)fk(x)=fk−1(x)×(1−x)。
也就是每次(1+x)(1+x)(1+x)和(1−x)(1-x)(1−x)交替乘n−1n-1n−1次,如果nnn是奇数,那么
fn−1(x)=((1+x)(1−x))n−12=(1−x2)n−12f_{n-1}(x)=((1+x)(1-x))^{\frac{n-1}{2}}=(1-x^2)^{\frac{n-1}{2}}fn−1(x)=((1+x)(1−x))2n−1=(1−x2)2n−1
用二项式定理拆开暴力算就好了,
如果nnn是偶数就直接再乘个1+x1+x1+x就好了。
时间复杂度:O(n)O(n)O(n)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10,P=1e9+7;
ll n,ans,fac[N],inv[N],f[N];
ll C(ll n,ll m)
{return fac[n]*inv[m]%P*inv[n-m]%P;}
signed main()
{scanf("%lld",&n);n--;inv[0]=inv[1]=fac[0]=1;for(ll i=2;i<=n;i++)inv[i]=P-(P/i)*inv[P%i]%P;for(ll i=1;i<=n;i++)inv[i]=inv[i-1]*inv[i]%P,fac[i]=fac[i-1]*i%P;for(ll i=0;i<=n/2;i++)f[i*2]=(i&1)?(P-C(n/2,i)):(C(n/2,i));if(n&1){for(ll i=n;i>=1;i--)f[i]=f[i]+f[i-1];}for(ll i=0,x;i<=n;i++)scanf("%lld",&x),(ans+=f[i]*x%P)%=P;printf("%lld\n",ans);return 0;
}