zoukankan      html  css  js  c++  java
  • 矩阵快速幂

    矩阵快速幂,对于很大的递推式需要要用到;

    贴几个题http://poj.org/problem?id=3070

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int M=2;
    const int mod=10000;
    struct node{
        int m[M][M];
        node operator*(node const &b)const{
            node res;
            memset(res.m,0,sizeof(res.m));
            for(int i=0;i<M;i++)
                for(int j=0;j<M;j++)
                    for(int k=0;k<M;k++)
                        res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod;
            return res;
        }
    };
    node quick(node base,int b)
    {
        node t;
        t.m[1][1]=t.m[0][0]=1;
        t.m[1][0]=t.m[0][1]=0;
        while(b)
        {
            if(b&1)
                t=t*base;
            b>>=1;
            base=base*base;
        }
        return t;
    }
    int main()
    {
        node s;
        s.m[0][0]=s.m[0][1]=s.m[1][0]=1;
        s.m[1][1]=0;
        int n;
        while(~scanf("%d",&n)&&n!=-1)
        {
            if(n==0)
            {
                printf("0
    ");
                continue;
            }
            node sum;
            sum=quick(s,n);
            printf("%d
    ",sum.m[0][1]);
        }
        return 0;
    }

    http://acm.hdu.edu.cn/showproblem.php?pid=1575

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    int n;
    const int mod=9973;
    const int M=10;
    struct node{
        int m[M][M];
        node operator*(node const &b)const{
            node res;
            memset(res.m,0,sizeof(res.m));
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    for(int k=0;k<n;k++)
                        res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod;
            return res;
        }
    };
    int quick(node &a,int k)
    {
        node t;
        memset(t.m,0,sizeof(t.m));
        for(int i=0;i<n;i++)
            t.m[i][i]=1;
        while(k)
        {
            if(k&1)
                t=t*a;
            k>>=1;
            a=a*a;
        }
        ll sum=0;
        for(int i=0;i<n;i++)
        {
            sum+=t.m[i][i];
            sum%=mod;
        }
        return sum;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int k;
            scanf("%d%d",&n,&k);
            node a;
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%d",&a.m[i][j]);
            printf("%d
    ",quick(a,k));
        }
        return 0;
    }

    http://acm.hdu.edu.cn/showproblem.php?pid=2256

    /*题目要求的是(sqrt(2)+sqrt(3))^2n %1024向下取整的值
    (sqrt(2)+sqrt(3))^2n=((sqrt(2)+sqrt(3))^2)n=(5+2*sqrt(6))^n
    改式子一定可以表示为f(x)=a[x]+b[x]*sqrt(6);
    所以f(x)=f(x-1)*(5+2*sqrt(6));
    既f(x)=(5+2*sqrt(6)*(a[x-1]+b[x-1]*sqrt(6)));
    |5  12|*|a[n-1]|=|a[n]|
    |2  5 |*|b[n-1]|=|b[n]|
    因此矩阵快速幂;
    然后就是取数的问题了,向下取整 
    由(5+2*sqrt(6))^n=a[n]+b[n]*sqrt(6)    (5-2*sqrt(6))^n=a[n]-b[n]*sqrt(6);
    所以(5+2*sqrt(6))^n+(5-2*sqrt(6))^n=2*a[n];
    因为(5-2*sqrt(6))^n约等于0;
    所以(5+2*sqrt(6))^n+0=2*a[n];
    所以(5+2*sqrt(6))^n=2*a[n]-1(向下取整)
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int M=2;
    const int mod=1024;
    const double P=sqrt((double)6);
    struct node{
        int m[M][M];
        node operator*(const node &b)const{
            node res;
            memset(res.m,0,sizeof(res.m));
            for(int i=0;i<M;i++)
                for(int j=0;j<M;j++)
                    for(int k=0;k<M;k++)
                        res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod;
            return res;
        }
    };
    int quick(node &a,int b)
    {
        if(b==1)
            return 9;
        node t;
        memset(t.m,0,sizeof(t.m));
        for(int i=0;i<M;i++)
            t.m[i][i]=1;
        b--;
        while(b)
        {
            if(b&1)
                t=t*a;
            b>>=1;
            a=a*a;
        }
        int suma=0;
        suma+=(t.m[0][0]*5+t.m[0][1]*2)%mod;
        return(2*suma-1)%mod;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            node a;
            memset(a.m,0,sizeof(a.m));
            a.m[0][0]=5;
            a.m[0][1]=12;
            a.m[1][0]=2;
            a.m[1][1]=5;
            printf("%d
    ",quick(a,n));
        }
        return 0;
    }

    http://acm.hdu.edu.cn/showproblem.php?pid=5451

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    const int M=2;
    typedef long long ll;
    ll mod;
    struct node{
        int m[M][M];
        node operator*(node const &b)const{
            node res;
            memset(res.m,0,sizeof(res.m));
            for(int i=0;i<M;i++)
                for(int j=0;j<M;j++)
                    for(int k=0;k<M;k++)
                        res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod;
            return res;
        }
    };
    node jksm(node base,int b){
        node t;
        t.m[0][0]=t.m[1][1]=1;
        t.m[0][1]=t.m[1][0]=0;
        while(b){
            if(b&1)
                t=t*base;
            b>>=1;
            base=base*base;
        }
        return t;
    }
    ll ksm(ll a,ll b,ll modd){
        ll t=1;
        while(b){
            if(b&1){
                t=t*a;
                t%=modd;
            }
            b>>=1;
            a=a*a;
            a%=modd;
        }
        return t;
    }
    int main(){
        int t;
        scanf("%d",&t);
        for(int k=1;k<=t;k++){
            ll x;
            scanf("%lld%lld",&x,&mod);
            node ans;
            ans.m[0][0]=5;
            ans.m[0][1]=12;
            ans.m[1][0]=2;
            ans.m[1][1]=5;
            x=ksm(2ll,x,(mod-1)*(mod+1))+1;
            ans=jksm(ans,x);
            ll sum=(2*ans.m[0][0]-1)%mod;
            printf("Case #%d: ",k);
            printf("%lld
    ",sum);
        }
        return 0;
    }
    View Code

     https://codeforces.com/problemset/problem/185/A

    题意:求出第n年,“向上”的三角形的个数

    递推式子:f[i]=3*f[i-1]+4^(n-1)-f[i-1]

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    const ll INF=1e18;
    const int M=2;
    const int mod=1e9+7;
    struct node{
        ll m[M][M];
        node operator*(node const &b)const{
            node res;
            memset(res.m,0ll,sizeof(res.m));
            for(int i=0;i<M;i++)
                for(int j=0;j<M;j++)
                    for(int k=0;k<M;k++)
                        res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod;
            return res;
        }
    };
    void solve(ll x){
        node t,sta,a;
        t.m[0][0]=t.m[1][1]=1;
        t.m[0][1]=t.m[1][0]=0;
        a.m[0][0]=2,a.m[0][1]=1;
        a.m[1][0]=0,a.m[1][1]=4;
    
        while(x){
            if(x&1)
                t=t*a;
            x>>=1;
            a=a*a;
        }
        
        printf("%I64d",(t.m[0][0]+t.m[0][1]+mod)%mod);
    }
    int main(){
        ll n;
    //    scanf("%I64d",&n);
        while(cin>>n){
            solve(n);
            cout<<endl;
        }
            
        
        return 0;
    }
    View Code
  • 相关阅读:
    json数组去重
    java socket API
    java网络编程精解demo1---读取用户控制台的输入的数据并显示
    【CodeForces 489A】SwapSort
    【CSU 1556】Pseudoprime numbers
    【CodeForces 472A】Design Tutorial: Learn from Math
    【CodeForces 605A】BUPT 2015 newbie practice #2 div2-E
    【UVALive 3905】BUPT 2015 newbie practice #2 div2-D-3905
    【HDU 4925】BUPT 2015 newbie practice #2 div2-C-HDU 4925 Apple Tree
    【UVA 401】BUPT 2015 newbie practice #2 div2-B-Palindromes
  • 原文地址:https://www.cnblogs.com/starve/p/10713350.html
Copyright © 2011-2022 走看看