首页 > 其他分享 >洛谷P4910题解

洛谷P4910题解

时间:2024-08-05 09:05:30浏览次数:9  
标签:arr 洛谷 题解 long 珠子 base pmatrix rst P4910

题目大意

现在穿T次手串,每根手串的长度分别为不同的n,有木和金两种珠子,相邻两颗珠子必须有一个是金。

题目思路分析

我们现在设穿到第n个珠子时用金的方案数为f[1][n],用木的方案数为f[0][n]
如果第n个珠子为金,那么前一颗珠子是什么都可以,因此f[1][n]=f[1][n-1]+f[0][n-1]
而如果第n个珠子为木,那么前一颗珠子必须是金,因此f[0][n]=f[1][n-1]

时间复杂度分析

如果使用纯递推,时间复杂度为O(Tn),如果Tn<=1e8的话,这道题可以轻易解决,然而,这道题n最大能到1e18,而T最大能到10,因此不能使用纯递推
因此需要把时间复杂度优化到O(T\(log_{2}(n)\)),就要用到矩阵加速。
这道题不太方便使用通项公式,因为f[1][n]=f[1][n-1]+f[0][n-1]=f[1][n-1]+f[1][n-2],是一个斐波那契数列,而斐波那契数列的通项公式中有\(\sqrt{5}\)这个无理数,可能会影响计算

所以总体思路就是矩阵快速幂加速递推

代码实现

矩阵乘法中 设A是一个P\(\times\)M,B是一个M\(\times\)Q,C是A乘以B的乘积,那么\(C_{i,j}\)=\(\sum_{k=1}^{M}A_{i,k} \times B_{k,j}\)
利用这个性质,我们可以将递推式转化为
\(\begin{pmatrix}f[0][i]&f[1][i]\end{pmatrix}\times\)

\[\begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix} \]

$=\begin{pmatrix}f[0][i+1]&f[1][i+1]\end{pmatrix}$
如果第一个用的是木珠子的话,最后一个只能用金珠子,这个要注意一下

AC代码

#include<bits/stdc++.h>
#define N 5
#define mod 1000000007
using namespace std;
long long n;
struct arr{
    long long a[N][N];
    arr(){
        memset(a,0,sizeof(a));
    }
}base,rst;
arr operator *(const arr &a,const arr &b){
    arr rst;
    for(int k=1;k<=N;k++){
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++){
                rst.a[i][j]=(rst.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
            }
        }
    }
    return rst;
}//矩阵乘法
void qpow(long long b) {
    while (b) {
        if (b & 1) rst = rst * base;
        base = base * base;
        b >>= 1;
    }
}//矩阵快速幂
void func(){
	scanf("%lld",&n);
    rst.a[1][1]=1,base.a[1][1]=rst.a[1][2]=0;//很简单粗暴的初始化
    base.a[1][2]=base.a[2][2]=base.a[2][1]=1;
    qpow(n-1);
    long long ans=rst.a[1][2];
    base.a[1][1]=rst.a[1][1]=0,rst.a[1][2]=1;
    base.a[1][2]=base.a[2][2]=base.a[2][1]=1;
    qpow(n-1);
    ans=(ans+rst.a[1][1]+rst.a[1][2])%mod;
    printf("%lld\n",ans);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--)func();
}

标签:arr,洛谷,题解,long,珠子,base,pmatrix,rst,P4910
From: https://www.cnblogs.com/wanxue/p/18342572

相关文章

  • ARC181题解(A-D)
    A-SortLeftandRight答案为0即已经排序。考虑答案为1的情况:一定是存在一个\(p\),使得\(\min_{i=1}^{p}a_i=p\)且\(a_p=p\),这时只要选择\(p\)即可。考虑答案为2的情况:如果\(a_1\neqn\operatorname{or}a_n\neq1\),一定可以通过先操作某个数,把\(1\)或者\(n\)......
  • Java环境变量配置的最佳实践和常见问题解决方案
    Java环境变量配置的最佳实践和常见问题解决方案大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java开发中,环境变量的配置是保证应用程序顺利运行的关键。无论是在本地开发环境还是生产环境,正确配置Java环境变量不仅能提升开发效率,还能避免许多常见......
  • [简单] 树上的dfs & bfs_洛谷P5908 猫猫和企鹅
    题目链接https://www.luogu.com.cn/problem/P5908题目大意:\[\begin{align*}&给定n个点构成一颗树每条边val=1\\&求从根节点Root=1开始\quad其它所有点v到Root的距离\mathrm{dis(v,Root)}<=\mathrm{d}的点的数量\\\end{align*}\]思路:1.bfs队列跑一遍记录每个点的......
  • 【LCA 树上两点的距离 判定点是否在某条边中】洛谷P3398 仓鼠找sugar
    题目链接:P3398仓鼠找sugar-洛谷|(luogu.com.cn)题目大意:判定一棵树上的两条边是否相交Tag:[LCA][树上两点间距离的计算][如何判断与点在某条路径上]思路:\[\begin{align}&1.建图\\&2.\text{dfs}然后\计算出每个点的深度和计\text{anc}(i,j)\\&3.根据树上路径......
  • Codeforces Round 891 (div.3) D题解析
    CodeForcesRound898(div4)D题.StrongVertices大致思路对于题目的给的式子,au-av>=bu-bv,我们可以通过移项得到au-bu>=av-bv,这样就能够构造出来一个ai-bi的项出来对于构造出来的项,我们可以遍历一遍用数组把每一个项存起来,找到值最大的项,值最大的项所对应的下标就是强顶......
  • 【秋招笔试】2024-08-03-科大讯飞秋招笔试题(算法岗)-三语言题解(CPP/Python/Java)
    ......
  • Luogu P1777 帮助 题解 [ 紫 ] [ 线性 dp ] [ 状压 dp ]
    帮助:大毒瘤!!!调了我2h,拍了我2h,最后没调出来,重写才AC。wdnmd。思路这题主要是线性dp,而状压dp只是最后在统计答案时的一个辅助。首先定义\(dp[i][j][k]\)为考虑前\(i\)本书,已经抽出来了\(j\)本,最后没被抽出来的一本书是高度\(k\)的最小混乱度。每次放入的书与最后一位......
  • Luogu P10842 Piggy and Trees 题解 [ 绿 ] [ 拆边 ] [ 贡献思维 ]
    PiggyandTrees:把路径拆成边的思维题。思路一看到这题的路径,就想到了LuoguP3177树上染色这题化路径为边的贡献,分别计算的思维。那么对于此题,先来观察题目里式子的意思:对于树上的每个无序点对,求出树上每个点到这些点对之间的最短路径的距离之和。枚举点对对应的就是前两......
  • 超好玩洛谷小游戏大全,好玩到停不下来(用洛谷的人都必须要知道,程序猿、OIer必备)
    Game啊你颓废了快点这个<tuifei break>{\color{White}\colorbox{Pink}{<tuifeibreak>}}<tuifei b......
  • 【面试题解答】一个有序数组 nums ,原地删除重复出现的元素
    面试题解答仅供学习文章目录面试题解答题目一、python代码1.1代码1.2示例用法1.2.1示例11.2.2示例2二、讲解2.1初始化2.2遍历2.3返回题目要解决这个问题,可以使用双指针方法进行原地修改,以确保每个元素最多出现两次。一、python代码1.1代码defr......