解法
就是数学优化+快速幂+除法取模结合在一起
首先,数学优化比较容易,最后肯定是要变成每遍历一个数就加一次。对于
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 <stdio.h>
#include <unordered_map>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <set>
#include <cmath>
#include <vector>
#include <algorithm>
#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);
}
}