任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6395
Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2564 Accepted Submission(s): 999
Problem Description
Let us define a sequence as below
Your job is simple, for each task, you should output Fn module 109+7.
⎧⎩⎨⎪⎪⎪⎪⎪⎪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
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
题意概括:
给出 A,B,C,D,P,N;
根据函数:
F(1)=A, F(2)=B, F(i)=C*F(i-2)+D*F(i-1)+p/i;
求 F( N );
解题思路:
一开始看错题目,以为 p/n 为 一个常数,其实题目里的 n 是变量(即题意里的 i );
如果是常数直接构造矩阵,矩阵快速幂跑一波即可,但是这里是是变量。
所以一开始选择了暴力 p/i ;p的范围是 1e9 果断超时。
怎么优化呢?
其实由于整型除法的向下取整,我们可以按 p/i 的种类分成一段一段的,这样大大缩短了暴力区间。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cmath> 5 #define LL long long 6 using namespace std; 7 const int MAXN = 11; 8 const int Mod = 1e9+7; 9 const int NN = 3; 10 int N, A, B, C, D, P; 11 struct mat 12 { 13 LL m[MAXN][MAXN]; 14 }base, ans; 15 16 mat muti(mat a, mat b) 17 { 18 mat res; 19 memset(res.m, 0, sizeof(res.m)); 20 for(int i = 1; i <= NN; i++) 21 for(int j = 1; j <= NN; j++){ 22 if(a.m[i][j]){ 23 for(int k = 1; k <= NN; k++){ 24 res.m[i][k] = (res.m[i][k] + a.m[i][j]*b.m[j][k])%Mod; 25 } 26 } 27 } 28 29 return res; 30 } 31 32 mat qpow(mat a, int n) 33 { 34 mat res; 35 memset(res.m, 0, sizeof(res.m)); 36 for(int i = 1; i <= NN; i++) res.m[i][i] = 1; 37 while(n){ 38 if(n&1) res = muti(res, a); 39 n>>=1; 40 a = muti(a, a); 41 } 42 return res; 43 } 44 45 46 int main() 47 { 48 int K, T_case; 49 scanf("%d", &T_case); 50 while(T_case--){ 51 memset(base.m, 0, sizeof(base.m)); 52 memset(ans.m, 0, sizeof(ans.m)); 53 scanf("%d %d %d %d %d %d", &A, &B, &C, &D, &P, &N); 54 if(N == 1){printf("%d ", A);continue;} 55 if(N == 2){printf("%d ", B);continue;} 56 else{ 57 base.m[1][2] = C; 58 base.m[2][2] = D; 59 base.m[2][1] = 1; 60 base.m[3][3] = 1; 61 base.m[3][2] = P/3; 62 ans.m[1][1] = A; 63 ans.m[1][2] = B; 64 ans.m[1][3] = 1; 65 int now = 3, x, len = 0, lst; 66 for(;now <= N; now = lst+1){ 67 x = P/now; 68 if(x != 0) lst = min(P/x, N); 69 else lst = N; 70 len = lst-now+1; 71 base.m[3][2] = x; 72 ans = muti(ans, qpow(base, len)); 73 } 74 } 75 printf("%lld ", ans.m[1][2]); 76 } 77 78 return 0; 79 }