HDU 6395 Sequence(矩阵快速幂+整除分块)

Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 615    Accepted Submission(s): 213


 

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

 

 

Recommend

chendu   |   We have carefully selected several similar problems for you:  6396 6395 6394 6393 6392 

 

【思路】

\left \lfloor \frac{P}{i} \right \rfloor在1 <= i <= n范围内取值是分段相同的,在每一段中,原递推式可以用矩阵快速幂优化,总时间复杂度是O(\sqrt{P}logN)。比赛中知道做法却让我写挂了,总是在细节上出错,感觉十分对不起跟我一起奋战的队友。

 

【代码】

//******************************************************************************
// File Name: 1010.cpp
// Author: Shili_Xu
// E-Mail: shili_xu@qq.com
// Created Time: 2018年08月13日 星期一 12时37分43秒
//******************************************************************************

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;

const int MOD = 1e9 + 7;

struct matrix {
    ll a[3][3];

    matrix()
    {
        memset(a, 0, sizeof(a));
    }

    matrix operator*(const matrix &another) const
    {
        matrix ans;
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                for (int k = 0; k < 3; k++)
                    ans.a[i][j] = (ans.a[i][j] + a[i][k] * another.a[k][j] % MOD);
        return ans;
    }
};

int t;
ll a, b, c, d, p, n;
matrix A, B;

matrix qpow(matrix a, int b)
{
    matrix ans;
    ans.a[0][0] = 1; ans.a[0][1] = 0; ans.a[0][2] = 0;
    ans.a[1][0] = 0; ans.a[1][1] = 1; ans.a[1][2] = 0;
    ans.a[2][0] = 0; ans.a[2][1] = 0; ans.a[2][2] = 1;
	while (b) {
        if (b & 1) ans = ans * a;
        a = a * a;
        b >>= 1;
    }
    return ans;
}

vector<ll> mul_matrix_vector(matrix a, vector<ll> b)
{
	vector<ll> ans;
	for (int i = 0; i < 3; i++) {
		ll now = 0;
		for (int j = 0; j < 3; j++) now = (now + a.a[i][j] * b[j]) % MOD;
		ans.push_back(now);
	}
	return ans;
}

void init()
{
	A.a[0][0] = 1; A.a[0][1] = 0; A.a[0][2] = 0;
	A.a[1][0] = 1; A.a[1][1] = d; A.a[1][2] = c;
	A.a[2][0] = 0; A.a[2][1] = 1; A.a[2][2] = 0;
}

int main()
{
	scanf("%d", &t);
	while (t--) {
		scanf("%lld %lld %lld %lld %lld %lld", &a, &b, &c, &d, &p, &n);
		if (n == 1) {
			printf("%lld\n", a);
			continue;
		}
		if (n == 2) {
			printf("%lld\n", b);
			continue;
		}
		init();
		vector<ll> now;
		now.push_back(0); now.push_back(b); now.push_back(a);
		for (ll l = 3, r; l <= n; l = r + 1) {
			if (p / l != 0)
				r = min(p / (p / l), n);
			else
				r = n;
			B = qpow(A, r - l + 1);
			now[0] = p / l;
			now = mul_matrix_vector(B, now);
		}
		printf("%lld\n", now[1]);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值