题目里有公式显示不了,直接传送门
公式: F1 = A F2 = B Fn = Fn-2 * C + Fn-1 * D + P / n
其中 A B C D P n 均为不定值, P / n 为计算机整数除法,即向下取整
很明显的是 前 2 项 * C + 前 1 项 * D,所以矩阵很好构造:
mat:
D 1
C 0
所以 F3 = F1 * mat[ 0 ][ 1] + F2 * mat[ 0 ][ 0 ] + P / 3
F4 = F2 * mat[ 0 ][ 1] + F3 * mat[ 0 ][ 0 ] + P / 3
所以这里要修改一下矩阵,把 P / n 也加进去
mat:
D 1 0
C 0 0
P/i 0 1
然后会发现 p / i 其实是有区间的,例如 p = 5 是 p / 1 = 5 , p / 2 = 2 , p / 3 = p / 4 = p / 5 = 1, p / 6 .... = 0
所以我们把 p 分区间做矩阵快速幂就可以了,然后在每个区间之间计算一次答案,运用到下一个区间即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
const ll mod = 1e9 + 7;
ll f[5];
struct Matrix{
ll m[3][3];
Matrix() {
mem(m, 0);
}
void init(){
m[0][0] = m[1][1] = m[2][2] = 1;
}
Matrix operator*(Matrix &mat){
Matrix ans;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
for(int k = 0; k < 3; k++){
ans.m[i][j] = (ans.m[i][j] + m[i][k] * mat.m[k][j]);
}
ans.m[i][j] %= mod;
}
}
return ans;
}
}X;
Matrix ksm(Matrix mat, int b){
Matrix ans;
ans.init();
while(b){
if(b & 1){
ans = ans * mat;
}
mat = mat * mat;
b >>= 1;
}
return ans;
}
ll getR(ll i,ll n,ll P){
ll num = P / i;
ll l = i,r = n;
while(l < r){
ll mid = r - (r - l) / 2;
if(P / mid == num){
l = mid;
}else if(P / mid < num){
r = mid - 1;
}else{
l = mid + 1;
}
}
return l;
}
int main(){
int T;
ll A,B,C,D,P,n;
scanf("%d",&T);
while(T--){
scanf("%lld %lld %lld %lld %lld %lld",&A,&B,&C,&D,&P,&n);
f[1] = A;
f[2] = B;
if(n <= 2){
printf("%lld\n",f[n]);
continue;
}
mem(X.m, 0);
X.m[0][0] = D, X.m[0][1] = 1;
X.m[1][0] = C, X.m[2][2] = 1;
ll f1 = f[2],f2 = f[1];
for(ll i = 3; i <= n; ){
ll l = i, r = getR(i,n,P);
X.m[2][0] = P / i;
Matrix ans = ksm(X, r - l + 1);
f[3] = (f1 * ans.m[0][0] % mod + f2 * ans.m[1][0] % mod + ans.m[2][0]) % mod;
f[4] = (f1 * ans.m[0][1] % mod + f2 * ans.m[1][1] % mod + ans.m[2][1]) % mod;
f1 = f[3];
f2 = f[4];
i = r + 1;
}
printf("%lld\n",f1);
}
return 0;
}