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

给出F的定义求F(n) % 1e9+7。

如果没有这个p/n,就是一个简单的矩阵快速幂。

向下取整的值在1-n中,显然每一个数出现的时候都是连续的一段,这样就可以分块地去求矩阵快速幂。

对于i,可以得出,p/i最后一次出现就是p/(p/i)。

以及为什么G++比C++提交快这么多啊嘤嘤嘤

#pragma once
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 100050;
const ll INF = (1LL << 62) - 1;
const double eps = 1e-8;
const ll mod = 1000000007;

int t, a, b, c, d, p, n;
struct matrix
{
    ll a[3][3];
    matrix ()
    {
        memset(a, 0, sizeof(a));
    }
};

matrix mul(matrix p, matrix o)
{
    matrix ans;
    for(int i = 0;i < 3;i++)
    {
        for(int k = 0;k < 3;k++)
        {
            for(int j = 0;j < 3;j++)
            {
                ans.a[i][j] = (ans.a[i][j] + p.a[i][k]*o.a[k][j]) % mod;
            }
        }
    }
    return ans;
}

matrix qpow(matrix a, ll x)
{
    matrix res;
    res.a[0][0] = res.a[1][1] = res.a[2][2] = 1;
    while(x > 0)
    {
        if(x & 1)
            res = mul(res, a);
        a = mul(a, a);
        x >>= 1;
    }
    return res;
}

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%d%d%d%d", &a, &b, &c, &d, &p, &n);
        if(n == 1) {printf("%d\n", a); continue;}
        else if(n == 2) {printf("%d\n", b); continue;}
        matrix res, tmp;
        res.a[0][0] = d, res.a[0][1] = c;
        res.a[1][0] = res.a[2][2] = 1;
        bool flag = 0;
        for(int i = 3;i <= n;i++)
        {
            if(p/i == 0)
            {
                tmp = res;
                tmp = qpow(tmp, n - i + 1);
                ll ans = (a*tmp.a[0][1] + b*tmp.a[0][0] + tmp.a[0][2]) % mod;
                printf("%d\n", ans);
                flag = 1;
                break;
            }
            ll j = min(n, p/(p/i));
            tmp = res;
            tmp.a[0][2] = p/i;
            tmp = qpow(tmp, j - i + 1);
            ll B = (a*tmp.a[0][1] + b*tmp.a[0][0] + tmp.a[0][2]) % mod;
            ll A = (a*tmp.a[1][1] + b*tmp.a[1][0] + tmp.a[1][2]) % mod;
            a = A, b = B;
            i = j;
        }
        if(!flag)
            printf("%d\n", b);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/82356807
今日推荐