• xiaowuga poj3735—Training little cats(特殊操作转化为矩阵操作)


    题意:有n只猫,对其进行k次操作,然后反复这样操作m次。

       其中g 表示 i 猫加1, e表示 i 猫为0;s表示  i 与 j 猫互换。

    解释一下样例:

    3 1 6
    g 1
    g 2
    g 2
    s 1 2
    g 3
    e 2

    则, (g 1 第一只猫加1):1, 0, 0;=>1,1,0=>1,2,0=>(s 1 2 第一只猫和第二只猫互相交换)2,1,0=>2,1,1=>(第2只猫为0)2,0,1;

    好了:我们知道初等矩阵:有交换,置0,哪一行加常数的作用。

    偷一张图:

    像这样!是不是就可以表示各个操作了,其实,这样就相当于每次操作产生一个转置矩阵的初等矩阵T, 那么k次操作就相当于产生k次矩阵。

    当然,直接把k次操作赋值给矩阵,其实相当于把k个转置矩阵的初等矩阵变成了一个,(慢慢想其实他们是等价的)。

    最后,有多少次这样的操作就快速幂m几次。

    答案就是矩阵[0][1--size]输出就行

    代码如下:注意(这个代码还是有问题的,我也不知道运行时错误)

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define ll long long
    ll n;
    struct jz
    {
        ll num[104][104];
        jz(){ memset(num, 0, sizeof(num)); }
        jz operator*(const jz&p)const
        {
            jz ans;
            for (int k = 0; k <= n;++k)
            for (int i = 0; i <= n;++i)
            for (int j = 0; j <= n; ++j)
                ans.num[i][j] = ans.num[i][j] + num[i][k] * p.num[k][j];
            return ans;
        }
    };
    jz POW(jz x, ll n)
    {
        jz ans;
        for (int i = 0; i <= n; ++i)ans.num[i][i] = 1;
        for (; n; n>>=1, x=x*x)
        if (n & 1)ans = ans*x;
        return ans;
    }
    int main()
    {
        ll m, k;
        while (cin>>n>>m>>k&&(n+m+k))
        {
            jz ans;
            for (int i = 0; i <= n; i++)ans.num[i][i] = 1;
            char ch[10];
            int i, j;
            while (k--)
            {
                cin >> ch >> i;
                if (ch[0] == 'g'){ ans.num[0][i]++;  }
                else if (ch[0] == 'e')
                {
                    for (int k = 0; k <= n; ++k)
                        ans.num[k][i] = 0;
                }
                else
                {
                    cin >> j;
                    for (int k = 0; k <= n; ++k)
                    {
                        swap(ans.num[k][i], ans.num[k][j]);
                    }
                }
            }
            ans = POW(ans, m);
            for (int i = 1; i <= n; ++i)
                cout << ans.num[0][i] << " \n"[i == n];
        }
        return 0;
    }
  • 相关阅读:
    QR code
    复制一个带random指针的链表
    运行时const
    海量处理 bitmap及区段划分
    socket编程随记
    BLS签名
    load balancing
    Bloom Filter (2)
    #include 的花样
    拓扑排序、Dijkstra、Prim/Kruskal、全部最短路径/传递闭包
  • 原文地址:https://www.cnblogs.com/ALINGMAOMAO/p/9503195.html
Copyright © 2020-2023  润新知