就是数学优化+快速幂+除法取模结合在一起
首先,数学优化比较容易,最后肯定是要变成每遍历一个数就加一次。对于 a m a_m am,它可以是子数组里的第1,2,…,m个,而它是第i个的子数组一共有 ( N + 1 − m ) (N+1-m) (N+1−m)个,当计算 P O W E R j {POWER}_j POWERj时,它的系数就是 1 j 1^j 1j, 2 j 2^j 2j, 3 j 3^j 3j,…, m j m^j mj,所以最后 a m a_m am的系数为:
∑ j = 1 k ∑ i = 1 m ( N + 1 − m ) i j = ( N + 1 − m ) ∑ i = 1 m ∑ j = 1 k i j = ( N + 1 − m ) ∑ i = 1 m i ( i k − 1 ) i − 1 \sum_{j=1}^k\sum_{i=1}^m(N+1-m)i^j\\ =(N+1-m)\sum_{i=1}^m\sum_{j=1}^ki^j\\ =(N+1-m)\sum_{i=1}^m\frac{i(i^k-1)}{i-1} j=1∑ki=1∑m(N+1−m)ij=(N+1−m)i=1∑mj=1∑kij=(N+1−m)i=1∑mi−1i(ik−1)
然后,显然对于 i k i^k ik那部分我们需要用快速幂来求
最后,对于 i ( i k − 1 ) i − 1 ( m o d p ) \frac{i(i^k-1)}{i-1}(mod\ p) i−1i(ik−1)(mod p),它不能通过分子和分母都分别取余来求。
这里要用到费马小定理:
如果 a a a和 p p p互质,那么 a p − 1 ( m o d p ) = 1 a^{p-1}(mod\ p)=1 ap−1(mod p)=1
令 p = 1 0 9 + 7 p=10^9+7 p=109+7,它是个质数,那么有 ( i − 1 ) p − 1 ( m o d p ) = 1 (i-1)^{p-1}(mod\ p)=1 (i−1)p−1(mod p)=1
所以 i ( i k − 1 ) ( i − 1 ) p − 2 ( m o d p ) = i ( i k − 1 ) i − 1 ( m o d p ) i(i^k-1)(i-1)^{p-2}(mod\ p)=\frac{i(i^k-1)}{i-1}(mod\ p) i(ik−1)(i−1)p−2(mod p)=i−1i(ik−1)(mod p)
这样就可以分别算出每个因子mod p
的值再相乘了
最后, ∑ i = 1 m \sum_{i=1}^m ∑i=1m算是一个前缀和,所以可以不用每次都循环
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MASK 0x10000
#define MAXN 16
using namespace std;
typedef long long lld;
const lld MOD = pow(10,9)+7;
lld FAST_POW(int i, int k) {
lld base = i, res = 1;
int e = k;
while (e>0) {
if(e&1) res = res*base%MOD;
base = base*base%MOD;
e = e>>1;
}
return res;
}
lld POW(int i,int k) {
if (i==1) return k;
else {
lld A = (i*(FAST_POW(i,k)-1))%MOD, B = FAST_POW(i-1,MOD-2);
return A*B%MOD;
}
}
int main() {
int t;
scanf("%d",&t);
for(auto round=1;round<=t;++round) {
lld n,k,x,y,c,d,e1,e2,f;
scanf("%lld%lld%lld%lld%lld%lld%lld%lld%lld",&n,&k,&x,&y,&c,&d,&e1,&e2,&f);
lld a = (x+y)%f;
lld ans = n*k*a%MOD;
lld cumprod = POW(1,k);
for(int i=1;i<n;++i) {
lld tmp = x;
x = (c*x+d*y+e1)%f;
y = (d*tmp+c*y+e2)%f;
a = (x+y)%f;
cumprod = (cumprod+POW(i+1,k))%MOD;
ans = (ans + cumprod*a% MOD*(n-i)% MOD)% MOD;
}
printf("Case #%d: %lld\n",round,ans%MOD);
}
}