HDU 4686 (推公式+矩阵快速幂)

题目连接:传送门

题意:

给定ai,bi的推倒公式,求sigma(ai*bi) ( 0<= i < n)

分析:

A0 = A0

Ai = Ai-1*Ax+Ay

B0 = B0

Bi = Bi-1*Bx+By

设Fi表示Ai*Bi

Fi = Ai * Bi

===>    Fi = (Ai-1*Ax + Ay)*(Bi-1*Bx + By)

===>    Fi = Ax*Bx*(Ai-1*Bi-1) + Ax*By*Ai-1 + Bx*Ay*Bi-1

===>    Fi = Fi-1 + Ax*By*Ai-1
+ Bx*Ay*Bi-1 + Ay*By

| F[i] |   | 1 , Ax*By , Bx*Ay , Ay*By |    | F[i-1] |

| Ai   | = | 0 ,   Ax  ,   0   ,   Ay  |  * |  Ai-1  |

| Bi   |   | 0 ,   0   ,   Bx  ,   By  |    |  Bi-1  |

| 1    |   | 0 ,   0   ,   0   ,    1  |    |    1   |

设sum[i] = sigma(ak*bk) ( 0<= k < i)

sum[i] = sum[i-1] + F[i]

sum[i] = sum[i-1] + Fi-1 + Ax*By*Ai-1 + Bx*Ay*Bi-1 + Ay*By

因此可以得到一个包含sum的状态转移矩阵

| sum[i] |   | 1 , 1 , Ax*By , Bx*Ay , Ay*By |    | sum[i-1] |

|  F[i]  |   | 0 , 1 , Ax*By , Bx*Ay , Ay*By |    |  F[i-1]  |

|    Ai        | =   | 0 ,     0 ,      Ax   ,         0   ,      Ay    |   *   |      Ai-1       |

|  Bi    |   | 0 , 0 ,   0   ,   Bx  ,   By  |    |   Bi-1   |

|  1     |   | 0 , 0 ,   0   ,   0   ,    1  |    |     1    |

这题需要注意的是n==0 输出0,注意使用long long,防止中间运算溢出

具体代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 5;

typedef __int64 LL;

const LL mod = 1e9+7;

struct matrix{
    LL a[N][N];
    matrix(){
        memset(a,0,sizeof(a));
    }
}I;

void init(){
    for(int i=0;i<N;i++)
        I.a[i][i]=1;
}

matrix multi(matrix A, matrix B){
    matrix C ;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            C.a[i][j]=0;
            for(int k=0;k<N;k++){
                C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%mod)%mod;
            }
        }
    }
    return C;
}

matrix quick(matrix A, LL n){
    matrix ans = I;
    while(n){
        if(n&1) ans = multi(A,ans);
        n>>=1;
        A=multi(A,A);
    }
    return ans;
}

int main()
{
    init();
    LL n,a0,b0,x1,y1,x2,y2;
    while(~scanf("%I64d",&n)){
        scanf("%I64d%I64d%I64d",&a0,&x1,&y1);
        scanf("%I64d%I64d%I64d",&b0,&x2,&y2);
        if(n==0){
            puts("0");
            continue;
        }
        x2=x2%mod;b0=b0%mod;y2=y2%mod;
        x1=x1%mod;a0=a0%mod;y1=y1%mod;
        matrix A=matrix();
        A.a[0][0]=1LL;
        A.a[0][1]=x1*x2%mod;
        A.a[0][2]=x1*y2%mod;
        A.a[0][3]=x2*y1%mod;
        A.a[0][4]=y1*y2%mod;
        A.a[1][1]=x1*x2%mod;
        A.a[1][2]=x1*y2%mod;
        A.a[1][3]=x2*y1%mod;
        A.a[1][4]=y1*y2%mod;
        A.a[2][2]=x1;
        A.a[2][4]=y1;
        A.a[3][3]=x2;
        A.a[3][4]=y2;
        A.a[4][4]=1LL;
        LL sum = 0;
        matrix ans = quick(A,n-1);
        sum =(sum + a0*b0%mod*ans.a[0][0]%mod)%mod;
        sum =(sum + a0*b0%mod*ans.a[0][1]%mod)%mod;
        sum =(sum + a0*ans.a[0][2]%mod)%mod;
        sum =(sum + b0*ans.a[0][3]%mod)%mod;
        sum =(sum + ans.a[0][4]%mod)%mod;
        printf("%I64d\n",sum);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-15 05:47:27

HDU 4686 (推公式+矩阵快速幂)的相关文章

CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)

问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高位数字不为0. 因此,符合我们定义的最小的有趣的数是2013.除此以外,4位的有趣的数还有两个:2031和2301. 请计算恰好有n位的有趣的数的个数.由于答案可能非常大,只需要输出答案除以1000000007的余数. 输入格式 输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000). 输

2016 pku campusH/OpenJ_POJ - C16H(推公式+矩阵快速幂)

传送门:http://poj.openjudge.cn/practice/C16H?lang=en_US 题面:描述 Wenwen has a magical ball. When put on an infinite plane, it will keep duplicating itself forever. Initially, Wenwen puts the ball on the location (x0, y0) of the plane. Then the ball starts

HDU 4686 Arc of Dream(快速幂矩阵)

题目链接 再水一发,构造啊,初始化啊...wa很多次啊.. #include <cstring> #include <cstdio> #include <string> #include <iostream> #include <algorithm> #include <vector> #include <queue> using namespace std; #define MOD 1000000007 #define

HDU 2604 Queuing (矩阵快速幂)

HDU 2604 Queuing (矩阵快速幂) ACM 题目地址:HDU 2604 Queuing 题意: n个人排队,f表示女,m表示男,包含子串'fmf'和'fff'的序列为O队列,否则为E队列,有多少个序列为E队列. 分析: 矩阵快速幂入门题. 下面引用巨巨解释: 用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1): 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 2254 奥运 题意: 中问题不解释. 分析: 根据floyd的算法,矩阵的k次方表示这个矩阵走了k步. 所以k天后就算矩阵的k次方. 这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和. 所以就是二分等比序列求和上场的时候了. 跟HDU 1588 Gauss Fibonacci的算法一样. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * B

HDU 2604 Queuing,矩阵快速幂

题目地址:HDU 2604 Queuing 题意: 略 分析: 易推出:   f(n)=f(n-1)+f(n-3)+f(n-4) 构造一个矩阵: 然后直接上板子: /* f[i] = f[i-1] + f[i-3] + f[i-4] */ #include<cstdio> #include<cstring> using namespace std; const int N = 4; int L, M; struct mtx { int x[N+1][N+1]; mtx(){ mem

hdu 2243 AC自动机 + 矩阵快速幂

// hdu 2243 AC自动机 + 矩阵快速幂 // // 题目大意: // // 给你一些短串,问在长度不超过k的任意串,包含至少一个这些短串的其中 // 一个.问这样的串有多少个. // // 解题思路: // // 首先, 包含和不包含是一种互斥关系,包含+不包含 = 全集u.全集的答案就是 // 26 ^ 1 + 26 ^ 2 + .... + 26 ^ k.不包含的比较好求.构建一个自动机,得到 // 一个转移矩阵A.表示状态i能到状态j的方法数.而这些状态中都是不包含所给的 //

HDU 3117 Fibonacci Numbers(矩阵快速幂+公式)

题目地址:HDU 3117 对于后四位可以用矩阵快速幂快速求出来,但前四位就没办法了.要知道斐波那契数列是有通项公式的,所以只能通过通项公式来求前四位,但公式不能求后四位,因为公式使用浮点数求的,精度显然不够,求前四位要用到对数. 通项公式为: f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n) 假设F[n]可以表示成 t * 10^k(t是一个小数),那么对于F[n]取对数log10,答案就为log10 t + K,此时很明显log10 t<

HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950 Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers