zoukankan      html  css  js  c++  java
  • poj 3735 Training little cats 矩阵快速幂+稀疏矩阵乘法优化

    题目链接

    题意:有n个猫,开始的时候每个猫都没有坚果,进行k次操作,g x表示给第x个猫一个坚果,e x表示第x个猫吃掉所有坚果,s x y表示第x个猫和第y个猫交换所有坚果,将k次操作重复进行m轮,问最后这n个猫各自有多少坚果。

    题解:构造(n+1)*(n+1)的单位矩阵,data[i][j]表示第i个猫与第j个猫进行交换,最后一列的前n项就是每个猫的坚果数目,s操作就交换对应行,矩阵快速幂时间复杂度O(n^3*log2(m))会超时,我们注意到在n*n的范围内每一行只有一个1,利用稀疏矩阵的乘法优化可以优化时间复杂度至O(n^2*log2(m))。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    struct matrix
    {
        ll data[105][105];
    };
    matrix ma;
    ll n,m,k,x,y;
    matrix multi(matrix a,matrix b)
    {
        matrix c;
        memset(c.data,0,sizeof(c.data));
        for(int i=0; i<=n; i++)
        for(int j=0; j<=n; j++)
        {
            //稀疏矩阵的乘法优化
            if(a.data[i][j]) //一个数一个数加进去
            for(int k=0; k<=n; k++)
            //注意这里的ijk已经改变位置
            c.data[i][k]+=a.data[i][j]*b.data[j][k];
        }
        return c;
    }
    matrix init(matrix *a)
    {
        memset((*a).data,0,sizeof((*a).data));
        for(int i=0;i<=n;i++)
        (*a).data[i][i]=1;
        //矩阵乘法的意义:
        //注意这里(*a).data[n][n]=1; 他的意义是继承上次操作的值
        //(*a).data[i][j]=1;继承的是交换的值 两个值加起来就是新的值
        return *a;
    }
    matrix pow1(matrix a,ll b)
    {
        matrix ans;
        init(&ans);
        while(b)
        {
            if(b&1)
            {
                ans=multi(ans,a);
                b--;
            }
            b>>=1;
            a=multi(a,a);
        }
        return ans;
    }
    void debug(matrix ans)
    {
        for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
        printf("%lld%c",ans.data[i][j],j==n?'
    ':' ');
    }
    int main()
    {
        while(scanf("%lld%lld%lld",&n,&m,&k)!=EOF)
        {
            if(n==0&&m==0&&k==0) break;
            char op[4];
            init(&ma);
            while(k--)
            {
                scanf("%s%lld",op,&x);
                x--;
                if(op[0]=='g')
                {
                    ma.data[x][n]++;
                }
                else if(op[0]=='s')
                {
                    scanf("%lld",&y);
                    y--;
                    for(int i=0;i<=n;i++)
                    swap(ma.data[x][i],ma.data[y][i]);
                }
                else if(op[0]=='e')
                {
                    for(int i=0;i<=n;i++)
                    ma.data[x][i]=0;
                }
            }
            matrix ans=pow1(ma,m);
            //debug(ans);
            for(int i=0;i<n;i++)
            printf("%lld%c",ans.data[i][n],i==n-1?'
    ':' ');
        }
        return 0;
    }
  • 相关阅读:
    jQuery使用(十三):工具方法
    jQuery使用(十二):工具方法之type()之类型判断
    马化腾成中国新首富:一个多月身家增长77亿美元
    滴滴:设立1000万美元专项基金,援助海外司机骑手
    疫情查询
    自动获取时间html代码
    搜索引擎你还用百度吗?为什么?
    实现QQ内打开链接跳转至浏览器
    QQ靓号资料空白且空间开通教程
    斐波那契数列计算html代码
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5939685.html
Copyright © 2011-2022 走看看