Product Oriented Recurrence(Codeforces Round #566 (Div. 2)E+矩阵快速幂+欧拉降幂)

传送门

题目

\[
\begin{aligned}
&f_n=c^{2*n-6}f_{n-1}f_{n-2}f_{n-3}&\\end{aligned}
\]

思路

我们通过迭代发现\(f_n\)其实就是由\(c^{x_1},f_1^{x_2},f_2^{x_3},f_3^{x_4}\)相乘得到,因此我们可以分别用矩阵快速幂求出\(x_1,x_2,x_3,x_4\),最后用快速幂求得答案。
对\(f_1,f_2,f_3\):
\[
\begin{aligned}
(x_n&&x_{n-1}&&x_{n-2})=(x_{n-1}&&x_{n-2}&&x_{n-3})
\left[
\begin{matrix}
1 & 1 & 0\1 & 0 & 1\1 & 0 & 0\\end{matrix}
\right]
\end{aligned}
\]
对\(c\):
\[
\begin{aligned}
(x_n&&x_{n-1}&&x_{n-2}&&n&&1)=(x_{n-1}&&x_{n-2} && x_{n-3} && n-1 && 1)
\left[
\begin{matrix}
1 & 1 & 0 & 0 & 0\1 & 0 & 1 & 0 & 0\1 & 0 & 0 & 0 & 0\2 & 0 & 0 & 1 & 0\2 & 0 & 0 & 1 & 1\\end{matrix}
\right]
\end{aligned}
\]
注意,由于我们处理出来的\(x_1,x_2,x_3,x_4\)都是指数部分,这里如果膜\(1e9+7\)的话是不对的,我们还需要对其进行欧拉降幂。

代码实现

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 2e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int f[10], a[10][10];

void mulself(int a[10][10]) {
    int c[10][10];
    memset(c, 0, sizeof(c));
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            for(int k = 0; k < 3; k++) {
                c[i][j] = (c[i][j] + (long long)a[i][k] * a[k][j] % (mod - 1)) % (mod - 1);
            }
        }
    }
    memcpy(a, c, sizeof(c));
}

void mul(int f[10], int a[10][10]) {
    int c[10];
    memset(c, 0, sizeof(c));
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            c[i] = (c[i] + (long long)f[j] * a[j][i] % (mod - 1)) % (mod - 1);
        }
    }
    memcpy(f, c, sizeof(c));
}

void mulself1(int a[10][10]) {
    int c[10][10];
    memset(c, 0, sizeof(c));
    for(int i = 0; i < 5; i++) {
        for(int j = 0; j < 5; j++) {
            for(int k = 0; k < 5; k++) {
                c[i][j] = (c[i][j] + (long long)a[i][k] * a[k][j] % (mod - 1)) % (mod - 1);
            }
        }
    }
    memcpy(a, c, sizeof(c));
}

void mul1(int f[10], int a[10][10]) {
    int c[10];
    memset(c, 0, sizeof(c));
    for(int i = 0; i < 5; i++) {
        for(int j = 0; j < 5; j++) {
            c[i] = (c[i] + (long long)f[j] * a[j][i] % (mod - 1)) % (mod - 1);
        }
    }
    memcpy(f, c, sizeof(c));
}

int qpow(int x, int n) {
    int res = 1;
    while(n) {
        if(n & 1) res = 1LL * res * x % mod;
        x = 1LL * x * x % mod;
        n >>= 1;
    }
    return res;
}

LL n;
int f1, f2, f3, c;

int main(){
    scanf("%lld%d%d%d%d", &n, &f1, &f2, &f3, &c);
    if(n == 1) return printf("%d\n", f1) * 0;
    if(n == 2) return printf("%d\n", f2) * 0;
    if(n == 3) return printf("%d\n", f3) * 0;
    n -= 3;
    LL ans = 1;
    f[0] = 1, f[1] = 0, f[2] = 0;
    a[0][0] = 1, a[0][1] = 1, a[0][2] = 0;
    a[1][0] = 1, a[1][1] = 0, a[1][2] = 1;
    a[2][0] = 1, a[2][1] = 0, a[2][2] = 0;
    LL x = n;
    while(x) {
        if(x & 1) mul(f, a);
        mulself(a);
        x >>= 1;
    }
    ans = ans * qpow(f3, f[0]) % mod;
    f[0] = 0, f[1] = 1, f[2] = 0;
    a[0][0] = 1, a[0][1] = 1, a[0][2] = 0;
    a[1][0] = 1, a[1][1] = 0, a[1][2] = 1;
    a[2][0] = 1, a[2][1] = 0, a[2][2] = 0;
    x = n;
    while(x) {
        if(x & 1) mul(f, a);
        mulself(a);
        x >>= 1;
    }
    ans = ans * qpow(f2, f[0]) % mod;
    f[0] = 0, f[1] = 0, f[2] = 1;
    a[0][0] = 1, a[0][1] = 1, a[0][2] = 0;
    a[1][0] = 1, a[1][1] = 0, a[1][2] = 1;
    a[2][0] = 1, a[2][1] = 0, a[2][2] = 0;
    x = n;
    while(x) {
        if(x & 1) mul(f, a);
        mulself(a);
        x >>= 1;
    }
    ans = ans * qpow(f1, f[0]) % mod;
    if(n == 1) f[0] = 2;
    if(n == 2) f[0] = 6;
    if(n == 3) f[0] = 14;
    if(n > 3) {
        n -= 3;
        f[0] = 14, f[1] = 6, f[2] = 2, f[3] = 3, f[4] = 1;
        memset(a, 0, sizeof(a));
        a[0][0] = a[0][1] = 1;
        a[1][0] = a[1][2] = 1;
        a[2][0] = 1;
        a[3][0] = 2, a[3][3] = 1;
        a[4][0] = 2, a[4][3] = a[4][4] = 1;
        while(n) {
            if(n & 1) mul1(f, a);
            mulself1(a);
            n >>= 1;
        }
    }
    ans = ans * qpow(c, f[0]) % mod;
    printf("%lld\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/Dillonh/p/11007112.html

时间: 2024-08-08 04:23:56

Product Oriented Recurrence(Codeforces Round #566 (Div. 2)E+矩阵快速幂+欧拉降幂)的相关文章

E. Product Oriented Recurrence(矩阵快速幂+欧拉降幂)

题目链接: https://codeforces.com/contest/1182/problem/E 题目大意:  f(x)=c^(2x−6)⋅f(x−1)⋅f(x−2)⋅f(x−3)    for x≥4x≥4. 给你f1,f2,f3,n,c.求第n项的结果. 具体思路: 看到递推式想到用矩阵快速幂优化:但是如果都是乘法的话,是无法化成矩阵相乘的形式的.然后就开始想怎么将乘法转换成加法.推了一个多小时也没有推出来.. 具体的解题过程如下: 对于每一项,这一项里面包含的f1 和 f2 和 f3

Codeforces Round #257 (Div. 2)B 矩阵快速幂

B. Jzzhu and Sequences time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn m

Codeforces Round #566 (Div. 2)

Codeforces Round #566 (Div. 2) A Filling Shapes 给定一个 \(3\times n\) 的网格,问使用 这样的占三个格子图形填充满整个网格的方案数 如果 \(n\) 是奇数,那么显然无解,否则考虑每个 \(3\times2\) 的方格正好能塞下两个这玩意而且必须这样塞进去,方案数为 \(2\),因此答案为 \(2^{n/2}\) B Plus from Picture 给定一个 \(h\times w\) 的矩阵,每个元素为 "." 或者

Codeforces Round #566 (Div. 2)题解

时间\(9.05\)好评 A Filling Shapes 宽度为\(3\),不能横向填 考虑纵向填,长度为\(2\)为一块,填法有两种 如果长度为奇数则显然无解,否则\(2^{n/2}\) B Plus from Picture 找到最靠上的十字轮廓(没有则直接无解),删掉后判断有无多余 C Beautiful Lyrics 以元音数量及最后的元音(如果没有元音的那些分别赋不同的负数)为一二关键词 开两个栈,代表诗头和诗尾 排序后,得到的以第一关键字的块,尽量把每一对放到诗尾,因为诗尾的也可以

Codeforces Round #566 (Div. 2)C(字符串,SET)

#include<bits/stdc++.h>using namespace std;string s[100007];set<int>st[100007][7];int t[207];int a[100007],b[100007][2],c[100007],d[100007][2];int main(){ t['a']=1; t['e']=2; t['i']=3; t['o']=4; t['u']=5; int n; cin>>n; for(int i=1;i<

Codeforces Round #305 (Div. 2)C---Mike and Frog(扩欧+乱搞)

Mike has a frog and a flower. His frog is named Xaniar and his flower is named Abol. Initially(at time 0), height of Xaniar is h1 and height of Abol is h2. Each second, Mike waters Abol and Xaniar. So, if height of Xaniar is h1 and height of Abol is

Codeforces Round #113 (Div. 2)E---Tetrahedron(矩阵,水题)

You are given a tetrahedron. Let's mark its vertices with letters A, B, C and D correspondingly. An ant is standing in the vertex D of the tetrahedron. The ant is quite active and he wouldn't stay idle. At each moment of time he makes a step from one

codeforces gym #101161G - Binary Strings(矩阵快速幂)

题目链接: http://codeforces.com/gym/101161/attachments 题意: 数据范围: 分析: ac代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define pii pair<int,int> const int maxn = 1e5+100; const int mod=1e9+7; struct Node{ ll num[4][4]; Node()

Codeforces 696D Legen...(AC自动机 + 矩阵快速幂)

题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少. POJ2778..复习下..太弱了都快不会做了.. 这个矩阵的乘法定义是不同的,m[i][j]=max(m1[i][k]+m2[k][j]),即从i走到k能获得的最大值与从k走到j能获得的最大值之和去更新从i到j能获得的最大值. 另外..关于矩阵内的初始值..用-1表示从i不能到j,比如初始的时候,i不能走一步到j结点这时值就应该设置成-1:而不能用0,因为0是有