HDU 6395 Sequence 【矩阵快速幂 && 暴力】

任意门: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

⎧⎩⎨⎪⎪⎪⎪⎪⎪F1F2Fn===ABCFn2+DFn1+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 , BCDPn.

1T200A,B,C,D1091P,n109
 

 

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\n", A);continue;}
55         if(N == 2){printf("%d\n", 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\n", ans.m[1][2]);
76     }
77 
78     return 0;
79 }
View Code

 

posted @ 2019-02-25 18:57  莜莫  阅读(150)  评论(0编辑  收藏  举报