zoukankan      html  css  js  c++  java
  • poj3735

    矩阵乘法

    题意:一个一维数组,全为0,对它进行一系列操作,包括某位+1,某位清零,交换某两位。将这一系列操作进行m次。问数组的最终情况。

    分析:数组的元素从第一位开始,把第0位附为1,我们构造一个n*n矩阵使得原1*n矩阵每乘以一次这个矩阵,得到的结果就相当于进行了一次一系列操作。然后用矩阵快速幂即可。构造矩阵的方法是:操作一,0行某列位置元素++;操作二,某列清零;操作三,交换两列。

    矩阵乘法需要优化:

        for (int i = 0; i < a.x; i++)
            for (int k = 0; k < a.y; k++)
                if (a.a[i][k])
                    for (int j = 0; j < b.y; j++)
                        ret.a[i][j] += a.a[i][k] * b.a[k][j];

    否则超时。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    using namespace std;

    #define maxn 110

    struct Matrix
    {
    long long x, y;
    long long a[maxn][maxn];
    } f, temp;

    long long n, m, r;

    Matrix mul(Matrix
    &a, Matrix &b)
    {
    Matrix ret;
    memset(ret.a,
    0, sizeof(ret.a));
    ret.x
    = a.x;
    ret.y
    = b.y;
    for (int i = 0; i < a.x; i++)
    for (int k = 0; k < a.y; k++)
    if (a.a[i][k])
    for (int j = 0; j < b.y; j++)
    ret.a[i][j]
    += a.a[i][k] * b.a[k][j];
    return ret;
    }

    Matrix power(Matrix
    &a, long long n)
    {
    Matrix m
    = a;
    Matrix ret;
    memset(ret.a,
    0, sizeof(ret.a));
    for (int i = 0; i < a.x; i++)
    ret.a[i][i]
    = 1;
    ret.x
    = ret.y = a.x;
    while (n > 0)
    {
    if (1 & n)
    ret
    = mul(ret, m);
    m
    = mul(m, m);
    n
    >>= 1;
    }
    return ret;
    }

    void input()
    {
    memset(f.a,
    0, sizeof(f.a));
    for (int i = 0; i <= n; i++)
    f.a[i][i]
    = 1;
    f.x
    = f.y = n + 1;
    for (int i = 0; i < m; i++)
    {
    int a, b;
    char ch[2];
    scanf(
    "%s", ch);
    if (ch[0] == 'g')
    {
    scanf(
    "%d", &a);
    f.a[
    0][a]++;
    }
    else if (ch[0] == 'e')
    {
    scanf(
    "%d", &a);
    for (int j = 0; j <= n; j++)
    f.a[j][a]
    = 0;
    }
    else
    {
    scanf(
    "%d%d", &a, &b);
    for (int j = 0; j <= n; j++)
    swap(f.a[j][a], f.a[j][b]);
    }
    }
    }

    void work()
    {
    Matrix ans;
    memset(ans.a,
    0, sizeof(ans.a));
    ans.x
    = 1;
    ans.y
    = n + 1;
    ans.a[
    0][0] = 1;
    ans
    = mul(ans, f);
    printf(
    "%lld", ans.a[0][1]);
    for (int i = 2; i <= n; i++)
    printf(
    " %lld", ans.a[0][i]);
    putchar(
    '\n');
    }

    int main()
    {
    //freopen("t.txt", "r", stdin);
    while (scanf("%lld%lld%lld", &n, &r, &m), n | r | m)
    {
    input();
    f
    = power(f, r);
    work();
    }
    return 0;
    }
  • 相关阅读:
    析构函数中的virtual是否必要?
    程序员必看的书
    UML类图几种关系的总结
    VS 2008的64位编译环境的安装和使用
    VB获取CAD属性值
    30分钟LINQ教程
    ADO.NET
    C#编写Windows服务程序图文教程
    Json的序列化与反序列化以及乱入的k_BackingField
    C#中的委托(Delegate)和事件(Event)
  • 原文地址:https://www.cnblogs.com/rainydays/p/2109955.html
Copyright © 2011-2022 走看看