Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1672 Accepted Submission(s): 608
Problem Description
Let us define a sequence as below
⎧⎩⎨⎪⎪⎪⎪⎪⎪F1F2Fn===ABC⋅Fn−2+D⋅Fn−1+⌊Pn⌋
Your job is simple, for each task, you should output Fn module 109+7.
Input
The first line has only one integer T, indicates the number of tasks.
Then, for the next T lines, each line consists of 6 integers, A , B, C, D, P, n.
1≤T≤200≤A,B,C,D≤1091≤P,n≤109
Sample Input
2 3 3 2 1 3 5 3 2 2 2 1 4
Sample Output
36 24
Source
2018 Multi-University Training Contest 7
思路:比较难处理的是 P/n,并不是个常数,因为是整除,P/n是由一段一段相同的数组成,每一段的p/n都相同,这样我们可以在同一段根据矩阵快速幂求出这一段的最后两项,根据这这一段求的最后两项和矩阵快速幂在求下一段的最后两项,直至到最后一段结束
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MOD = 1e9 + 7;
struct Mat
{
LL M[3][3];
Mat(){memset(M,0,sizeof(M));}
};
Mat mul(Mat a,Mat b)
{
Mat c;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
for(int k = 0; k < 3; k++) {
c.M[i][j] = (c.M[i][j] + a.M[i][k] * b.M[k][j] % MOD) % MOD;
}
}
}
return c;
}
Mat qpow(Mat a,int b)
{
Mat res;
for(int i = 0; i < 3; i++) {
res.M[i][i] = 1;
}
while(b) {
if(b & 1) res = mul(res,a);
a = mul(a,a);
b >>= 1;
}
return res;
}
int main(void)
{
/*for(int i = 1; i <= 50; i++) {
printf("%d ",50 / i);
}
printf("\n-----------------------\n");*/
int T;
cin >> T;
LL A,B,C,D,P,n,a,b;
while(T--) {
cin >> A >> B >> C >> D >> P >> n;
if(n == 1) cout << A << endl;
else if(n == 2) cout << B << endl;
else {
Mat f;
f.M[0][0] = D;
f.M[0][1] = C;
f.M[1][0] = 1;
f.M[2][2] = 1;
for(LL i = 3; i <= n;) {
if(P / i == 0) {
Mat w = f;
w = qpow(w,n - i + 1);
B = (w.M[0][0] * B % MOD + w.M[0][1] * A % MOD + w.M[0][2]) % MOD;
break;
}
LL j = min(n,P / (P / i));
//printf("%lld %lld\n",P / i,j - i + 1);
Mat w = f;
w.M[0][2] = P / i;
w = qpow(w,j - i + 1);
//cout << w.M[1][0] << " ---- \n";
a = (w.M[1][0] * B % MOD + w.M[1][1] * A % MOD + w.M[1][2]) % MOD;
b = (w.M[0][0] * B % MOD + w.M[0][1] * A % MOD + w.M[0][2]) % MOD;
A = a,B = b;
//cout << A << " " << B << endl;
i = j + 1;
//printf("%lld\n",i);
}
cout << B << endl;
}
}
return 0;
}
/*
5
1 2 3 4 50 50
*/