构造矩阵+矩阵快速幂 POJ3735

https://vjudge.net/contest/182427#problem/C

这题题意如下,有n 只猫咪,三种关于花生的命令 ( 得花生,吃花生,交换花生 ) ,给出一套命令,重复 n 次,问最后每只猫咪得到多少花生。
M那么大,毫无疑问,矩阵快速幂。

先构造一个单位矩阵,因为只需在单位矩阵上进行操作,然后用操作完之后得到的矩阵乘以初始的状态就得到最终的状态。
看下图:

第 i 只猫咪得花生就是在矩阵的第 i 行的最后一列加上1;
注意:如果是 n 只猫咪的话,要用n+1维的矩阵,即n+1维的方阵,多出来的一个才能起到操作的作用!

下面是重点,就是矩阵的快速幂,思路和整数的快速幂一样,不过该过程中会用稀疏矩阵出现,故可借此优化,即跳过0元素;

代码如下:

#include
#include
#include
#include
#define ll long long
using namespace std;
ll n,m,k;
struct matrix
{
    ll a[120][120];
} init;
matrix multi(matrix x,matrix y)
{
    matrix ans;
    memset(ans.a,0,sizeof(ans.a));
    for(int i=0; i<=n; i++)//减少运算量的矩阵乘法,如果为零就不用相乘
    {
        for(int k=0; k<=n; k++)
        {
            if(x.a[i][k])
            {
                for(int j=0; j<=n; j++)
                    ans.a[i][j]+=x.a[i][k]*y.a[k][j];
            }
        }
    }
    return ans;
}

matrix mq(ll m)//矩阵快速幂
{
    if(m==1)
        return init;
    matrix ans;
    memset(ans.a,0,sizeof(ans.a));//这里必须要初始化,不然会wrong
    for(int i=0;i<=n;i++)
            ans.a[i][i]=1;
    while(m)
    {
        if(m&1)ans=multi(ans,init);
        m>>=1;
        init=multi(init,init);
    }
    return ans;
}
int main()
{
    char c[10];
    int x,y;
    while(~scanf("%lld%lld%lld",&n,&m,&k),n+m+k)
    {
        memset(init.a,0,sizeof(init.a));
        for(int i=0; i<=n; i++)
            init.a[i][i]=1;
        for(int i=0; iscanf("%s",c);
            if(c[0]=='g')
            {
                scanf("%d",&x);
                init.a[x-1][n]++;
            }
            else if(c[0]=='e')
            {
                scanf("%d",&x);
                for(int j=0; j<=n; j++)
                    init.a[x-1][j]=0;
            }
            else
            {
                scanf("%d %d",&x,&y);
                for(int j=0; j<=n; j++)
                    swap(init.a[x-1][j],init.a[y-1][j]);
            }
        }
        matrix ans=mq(m);
        for(int i=0; i1; i++)
            printf("%lld ",ans.a[i][n]);
        printf("%lld\n",ans.a[n-1][n]);
    }
}

你可能感兴趣的:(数学)