zoukankan      html  css  js  c++  java
  • 05 矩阵优化 (斜率优化等待补)

    矩阵快速幂

    https://www.luogu.com.cn/problem/P3390
    就是矩阵乘法+快速幂,本来想用宏定义定义mod,结果不知道为什么会出错,改成const就过了

    //#include<iostream>
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    const ll max_n=1e5+1000;
    const ll inf=0x3f3f3f3f;
    ll n,m,a[120][120];
    struct mat{
        int len;
        ll m[110][110];
        mat times(mat b){
            mat c;
            c.len=len;
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    ll res=0;
                    for(int v=0;v<len;v++){
                        res+=m[i][v]*b.m[v][j]%mod;
                    }c.m[i][j]=(res+mod)%mod;
                }
            }
            return c;
        }
        void output(){
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    cout<<m[i][j]<<' ';
                }cout<<endl;
            }
        }
        void uni(){
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    if(i==j) m[i][j]=1;
                    else m[i][j]=0;
                }
            }
        }
    };
    mat qmp(mat a,ll k){
        mat res,x;
        res.len=a.len;
        x.len=a.len;
        res.uni(),x=a;
        while(k){
            if(k&1){
                res=res.times(x);
            }x=x.times(x);
            k>>=1;
        }
        return res;
    }
    int main(){
        //freopen("in.txt","r",stdin);
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        cin>>n>>m;
        mat a;
        a.len=n;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cin>>a.m[i][j];
            }
        }
        qmp(a,m).output();
        return 0;
    }
    

    矩阵加速

    https://www.luogu.com.cn/problem/P1939
    板子题,矩阵长这样:

    \( \left[ \begin{array}{c} a_n\\ a_{n-1}\\ a_{n-2}\\ \end{array} \right] =\left[ \begin{matrix} 1& 0& 1\\ 1& 0& 0\\ 0& 1& 0\\ \end{matrix} \right] \left[ \begin{array}{c} \begin{array}{c} a_{\begin{array}{c} n-1\\ \end{array}}\\ a_{n-2}\\ \end{array}\\ a_{n-3}\\ \end{array} \right] \)
    然后就是套上快速幂求就可以了,结果就是第一行的和

    //#include<iostream>
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    const ll max_n=1e5+1000;
    const ll inf=0x3f3f3f3f;
    ll n,m,a[120][120];
    struct mat{
        int len;
        ll m[110][110];
        mat times(mat b){
            mat c;
            c.len=len;
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    ll res=0;
                    for(int v=0;v<len;v++){
                        res+=m[i][v]*b.m[v][j]%mod;
                    }c.m[i][j]=(res+mod)%mod;
                }
            }
            return c;
        }
        void output(){
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    cout<<m[i][j]<<' ';
                }cout<<endl;
            }
        }
        void uni(){
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    if(i==j) m[i][j]=1;
                    else m[i][j]=0;
                }
            }
        }
    };
    mat qmp(mat a,ll k){
        mat res,x;
        res.len=a.len;
        x.len=a.len;
        res.uni(),x=a;
        while(k){
            if(k&1){
                res=res.times(x);
            }x=x.times(x);
            k>>=1;
        }
        return res;
    }
    int main(){
        //freopen("in.txt","r",stdin);
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        cin>>n;
        mat a,ans;
        a.len=3;
        a.m[0][0]=1,a.m[0][1]=0,a.m[0][2]=1;
        a.m[1][0]=1,a.m[1][1]=0,a.m[1][2]=0;
        a.m[2][0]=0,a.m[2][1]=1,a.m[2][2]=0;
        while(n--){
            cin>>m;
            if(m<=3){
                cout<<1<<endl;
                continue;
            }else{
                ans=qmp(a,m-3);
                ll res=(ans.m[0][0]+ans.m[0][1]+ans.m[0][2])%mod;
                cout<<res<<endl;
            }
            
        }
        
        return 0;
    }
    

    斐波那契公约数

    https://www.luogu.com.cn/problem/P1306
    事实证明,打表乃找规律第一要义,打出来前20x20个结果,发现结果总就那么几个值,又发现这些值全是本身数列里的元素,结果就可以得到以下规律:

    \[gcd\left( f_n,f_m \right) =f_{gcd\left( n,m \right)} \]

    然后就简单了,同上。

    //#include<iostream>
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e8;
    const ll max_n=1e5+1000;
    const ll inf=0x3f3f3f3f;
    ll n,m,a[120][120];
    struct mat{
        int len;
        ll m[110][110];
        mat times(mat b){
            mat c;
            c.len=len;
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    ll res=0;
                    for(int v=0;v<len;v++){
                        res+=m[i][v]*b.m[v][j]%mod;
                    }c.m[i][j]=(res+mod)%mod;
                }
            }
            return c;
        }
        void output(){
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    cout<<m[i][j]<<' ';
                }cout<<endl;
            }
        }
        void uni(){
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    if(i==j) m[i][j]=1;
                    else m[i][j]=0;
                }
            }
        }
    };
    mat qmp(mat a,ll k){
        mat res,x;
        res.len=a.len;
        x.len=a.len;
        res.uni(),x=a;
        while(k){
            if(k&1){
                res=res.times(x);
            }x=x.times(x);
            k>>=1;
        }
        return res;
    }
    ll gcd(ll a,ll b){
        if(b==0){
            return a;
        }else return gcd(b,a%b);
    }
    int main(){
        //freopen("in.txt","r",stdin);
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        cin>>n>>m;
        mat a,ans;
        a.len=2;
        a.m[0][0]=1,a.m[0][1]=1;
        a.m[1][0]=1,a.m[1][1]=0;
        n=gcd(n,m);
        if(n<=2){
            cout<<1<<endl;
        }else{
            ans=qmp(a,n-2);
            cout<<(ans.m[0][0]+ans.m[0][1])%mod<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    随机产生字母a--z, A-Z 的任意组合
    如何获取HttpServletResponse里面的内容
    线上问题:如何定位解决CPU高占有率
    tomcat+apache 实现负载均衡之一:同一台电脑部署2个以上tomcat
    drozer与adb工具的安装与使用
    CVE-2012-0002(MS12-020)3389远程溢出漏洞
    VMware每次联网都需要还原默认设置解决办法
    Ubuntu设置右键打开终端
    Metasploits之Adobe阅读器漏洞
    Metasploits之ms10_018
  • 原文地址:https://www.cnblogs.com/Zabreture/p/13412452.html
Copyright © 2011-2022 走看看