探索(数学)(矩阵快速幂)(快速乘)



一句话题意:三维空间划分四维空间,最多能划分成多少个部分。

我们直接想四维的不好想,但是一般这种题我们考虑从低维开始做起。

在经过手算之后我们可以发现:

设\(f(x)\)为零维(点)切一维(线)最多划分的部分,递推式:\(f(x)=f(x-1)+1\)

设\(g(x)\)为一维(线)切二维(平面)最多划分的部分,递推式:\(g(x)=g(x-1)+f(x-1)\)

设\(k(x)\)为二维(平面)切三维(空间)最多划分的部分,递推式:\(k(x)=k(x-1)+g(x-1)\)

设\(h(x)\)为三维(空间)切四维最多划分的部分,递推式:\(h(x)=h(x-1)+k(x-1)\)

那么我们很容易看出这是一个递推。但是因为数据范围很大,所以我们考虑构造矩阵进行矩阵快速幂加速运算。(不会打mathjax矩阵,只能凑合一下了)

1 1 0 0 0
0 1 1 0 0
0 0 1 1 0
0 0 0 1 1
0 0 0 0 1

然后初始矩阵[1,f(0),g(0),k(0),h(0)]

但是因为数据实在很大,矩阵快速幂进行乘的时候很可能炸long long,所以我们用快速乘来保证数在mod范围内。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 40
using namespace std;
long long n,m;
long long f[MAXN];
struct Node{long long t[MAXN][MAXN];};
Node init;
inline long long multi(long long x,long long y,long long mod)
{
    long long ans=0;
    while(y)
    {
        if(y&1) ans=(ans+x)%mod;
        x=(x+x)%mod;
        y>>=1;
    }
    return ans%mod;
}
inline Node mul(Node x,Node y)
{
    Node cur;
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
            cur.t[i][j]=0;
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
            for(int k=1;k<=5;k++)
                cur.t[i][j]=(cur.t[i][j]+multi(x.t[i][k],y.t[k][j],m))%m;
    return cur;
}
inline void solve()
{
    long long cur[MAXN];
    memset(cur,0,sizeof(cur));
    for(int j=1;j<=5;j++)
        for(int k=1;k<=5;k++)
            cur[j]=(cur[j]+multi(f[k],init.t[k][j],m))%m;
    for(int i=1;i<=5;i++)
        f[i]=cur[i];
}
int main()
{
    freopen("discover.in","r",stdin);
    freopen("discover.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    f[1]=1;
    f[2]=1;
    f[3]=1;
    f[4]=1;
    f[5]=1;
    for(int i=1;i<=5;i++) init.t[i][i]=1;
    init.t[1][2]=1;
    init.t[2][3]=1;
    init.t[3][4]=1;
    init.t[4][5]=1;
    while(n)
    {
        if(n&1) solve();
        init=mul(init,init);
        n>>=1;
    }
    printf("%lld\n",f[5]%m);
    return 0;
}

原文地址:https://www.cnblogs.com/fengxunling/p/9800905.html

时间: 2024-08-11 21:48:46

探索(数学)(矩阵快速幂)(快速乘)的相关文章

hdu 5187 快速幂快速乘法

http://acm.hdu.edu.cn/showproblem.php?pid=5187 Problem Description As one of the most powerful brushes, zhx is required to give his juniors n problems. zhx thinks the ith problem's difficulty is i. He wants to arrange these problems in a beautiful wa

取模性质,快速幂,快速乘,gcd和最小公倍数

一.取模运算 取模(取余)运算法则: 1. (a+b)%p=(a%p+b%p)%p; 2.(a-b)%p=(a%p-b%p)%p; 3.(a*b)%p=(a%p * b%p)%p; 4.(a^b)%p=(   (a%p)^b  )%p; 5. (  (a+b)%p+c  )%p=( a+(b+c)%p  )%p; 6.( a*(b*c)%p )%p =( c*(a*b)%p )%p; 7.( (a+b)%p*c )%p= ( (a*c)%p + (b*c)%p )%p; 几条重要性质: 1.a≡

HDU - 5187 zhx&#39;s contest(快速幂+快速乘法)

作为史上最强的刷子之一,zhx的老师让他给学弟(mei)们出n道题.zhx认为第i道题的难度就是i.他想要让这些题目排列起来很漂亮. zhx认为一个漂亮的序列{ai}下列两个条件均需满足. 1:a1..ai是单调递减或者单调递增的. 2:ai..an是单调递减或者单调递增的. 他想你告诉他有多少种排列是漂亮的.因为答案很大,所以只需要输出答案模p之后的值. Input Multiply test cases(less than 10001000). Seek EOF as the end of

算法录 之 快速幂快速乘和矩阵快速幂。

1: 问题如下: 求 a^n % m 的值是多少?n是1到10^18次方的一个整数. 求一个数的n次方,朴素的算法就是直接for循环,O(N)的复杂度. 但是对于这个问题n实在是太大了,O(N)也会超时,那么需要更快的算法,快速幂算法. 要求 a^n,如果知道了 a^(n/2) 次方的话,再来个平方就可以了. 那么按照这个思路就能运用分治的思想了. 代码如下: 1 int _pow(int a,long long n,int m) { 2 if(n==0) return 1 % m; 3 4 l

【BZOJ 1409】 Password 数论(扩展欧拉+矩阵快速幂+快速幂)

读了一下题就会很愉快的发现,这个数列是关于p的幂次的斐波那契数列,很愉快,然后就很愉快的发现可以矩阵快速幂一波,然后再一看数据范围就......然后由于上帝与集合对我的正确启示,我就发现这个东西可以用欧拉函数降一下幂,因为两个数一定互质因此不用再加一个phi(m),于是放心的乘吧宝贝!! #include <cstdlib> #include <cstring> #include <cstdio> #include <iostream> #include &

HDOJ M斐波那契数列 4549【矩阵快速幂+快速幂+费马小定理+欧拉函数】

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 2096    Accepted Submission(s): 596 Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给

hdu 5187 快速幂+快速乘法

简单找出规律,答案为(2^n-2 )%p(1特判) 然而  n,p的最大值为 1e18 因此显然要快速幂,而且由于1e18 的平方超long long 所以在乘的时候要用快速乘法,快速乘法的原理和快速幂一样,a^b是 b个a相乘 ,快速乘法是b个a相加 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; long

快速幂&amp;&amp;快速幂驱魔

以下以求a的b次方来介绍[1] 把b转换成二进制数. 该二进制数第i位的权为 例如 11的二进制是1011 11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1 因此,我们将a¹¹转化为算 __int64 pow3(inta,intb)//快速幂 { __Int64 r=1,base=a; while(b) { if(b&1) r*=base; base*=base; b>>=1;//① } return r; } __int64 qpow(int a,int b,int c)

ACM:a^b%p-数论-快速幂-快速乘

a^b Time Limit: 1000MS   Memory Limit: 65535KB   64bit IO Format: Description 求a的b次方,取模mod(1<=a,b,mod<=1e18) Input 多组输入,每组数据一行,3个正整数,分别为a,b,mod Output 每组数据输出一行,为答案 Sample Input 2 10 10000000 5 100 1 0 2 37 Sample Output 1024 0 0 //模版题,主要是考虑到1e18的巨大,

快速幂&amp;快速乘法

尽管快速幂与快速乘法好像扯不上什么关系,但是东西不是很多,就一起整理到这里吧 快速幂思想就是将ax看作x个a相乘,用now记录当前答案,然后将指数每次除以2,然后将当前答案平方,如果x的2进制最后一位为1的话,就将答案乘以现在的数.快速乘法类似,只是将a*x看作x个a相加. 代码 1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int mi(int a,int x) 5 { 6 int ans=1;