考虑转期望。
对称具有期望线性性,即我们可以关于期望位置对称。
那么一次对称操作变成 $a_i = a_{i-1} + a_{i+1} - a_i$。
考虑差分数组的变化,发现是交换了 $a_i - a_{i-1}$ 与 $a_{i+1} - a_i$。
发现 $m$ 不大,但是 $K$ 大。
发现既然是交换操作,那么可以维护一个置换,做快速幂即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include<bits/stdc++.h> using namespace std; #define int long long const int maxn=1e5; const int mod=1e9+7; struct Node{int p[maxn+5];}; int n,m,K; int a[maxn+5]; int b[maxn+5]; int c[maxn+5]; Node bs,res; inline int Fpow(int x,int y){ int res=1; for(;y;x=x*x%mod,y>>=1) if(y&1) res=res*x%mod; return res; } Node operator*(Node x,Node y){ Node z; for(int i=1;i<n;i++) z.p[i]=y.p[x.p[i]]; return z; } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=1;i<n;i++){ b[i]=a[i+1]-a[i]; bs.p[i]=i; res.p[i]=i; } scanf("%lld%lld",&m,&K); int x; for(int i=1;i<=m;i++){ scanf("%lld",&x); swap(bs.p[x],bs.p[x-1]); } int t=K; for(;t;bs=bs*bs,t>>=1) if(t&1) res=res*bs; for(int i=1;i<n;i++) c[i]=b[res.p[i]]; for(int i=2;i<=n;i++) a[i]=a[i-1]+c[i-1]; t=Fpow(2,K%(mod-1)*m%(mod-1)); for(int i=1;i<=n;i++) printf("%lld ",((t*a[i]%mod)+mod)%mod); return 0; }
|