ACM: 矩阵建模 数论题 poj 3735 (…

来源:互联网 发布:提花组织软件 编辑:程序博客网 时间:2024/05/24 04:33
Training little cats
Description

Facer's pet cat just gave birth to a brood of little cats.Having considered the health of those lovely cats, Facer decides tomake the cats to do some exercises. Facer has well designed a setof moves for his cats. He is now asking you to supervise the catsto do his exercises. Facer's great exercise for cats contains threedifferent moves:
g i : Let the ith cat take a peanut.
e i : Let the ith cat eat all peanuts it have.
s i j : Let the ith cat and jth cat exchange their peanuts.
All the cats perform a sequence of these moves and must repeat it mtimes! Poor cats! Only Facer can come up with such embarrassingidea.
You have to determine the final number of peanuts each cat have,and directly give them the exact quantity in order to savethem.

Input

The input file consists of multiple test cases, ending withthree zeroes "0 0 0". For each test case, three integers n,m and k are given firstly, where n is thenumber of cats and k is the length of the move sequence. Thefollowing k lines describe the sequence.
(m≤1,000,000,000, n≤100, k≤100)

Output

For each test case, output n numbers in a single line,representing the numbers of peanuts the cats have.

Sample Input

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

Sample Output

2 0 1

题意: 要你训练猫猫, n只小猫, 要重复对它们进行k个动作m次. 要你求出最后的每只小猫有的peanuts.

解题思路:
    1.这题一开始看着就像模拟题, 不过一看重复的次数m<= 1,000,000,000,打消念头了.
    2.其实这题灵感是来自上一题poj 3613, 二分求矩阵的幂次运算.
    3.这题是需要自己建立矩阵. (难点)
    问题分析:
     (1).原问题可以看成是对一个一维(n+1)矩阵, g:某位+1, e: 某位清零, s: 某两位交换. 进行m次
     (2).现在我们不妨把一维矩阵扩展成(n+1)*(n+1)的矩阵, 并且在对角线上记录每操作一次是否有增量.
    例如:
      初始化问题矩阵: 1 0 0 0 0                1 2 0 1 0
                    0 1 0 0 0     1次操作后   0 0 0 0 0
                    0 0 1 0 0      ===>      0 1 0 0 0
                    0 0 0 1 0                0 0 0 1 0
                    0 0 0 0 1                0 0 0 0 1
      (3).接下来的问题就是怎么将矩阵相乘求解, 显然是矩阵二分幂次运算.(poj 3613思路)
     while(n)  //temp初始化是单位矩阵.
     {
       if(n%2 == 1)
          temp = multiply(temp,A);
       A = multiply(A,A);
       n/=2;
    
     4.WA了几次的原因, matrix矩阵中的要用long long.

代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 105

struct matrix
{
    int row, column;
    long long g[MAX][MAX];
};

int n, m, K;
matrix a;

inline void swap(long long &a, long long &b)
{
    long long temp = a;
    a = b;
    b = temp;
}

void read_graph()
{
    memset(a.g,0,sizeof(a.g));
    a.row = a.column = n+1;
    for(int i = 0; i < a.row; ++i)
        a.g[i][i] = 1;

    int num1, num2;
    char ch[2];
    for(int i = 0; i < K; ++i)
    {
        scanf("%s",ch);
        if(ch[0] == 'g')
        {
            scanf("%d",&num1);
            a.g[0][num1]++;
        }
        else if(ch[0] == 'e')
        {
            scanf("%d",&num1);
            for(int j = 0; j <= n; ++j)
                a.g[j][num1] = 0;
        }
        else
        {
            scanf("%d %d",&num1,&num2);
            for(int j = 0; j <= n; ++j)
                swap(a.g[j][num1], a.g[j][num2]);
        }
    }
}

matrix multiply(matrix &A, matrix &B)
{
    matrix c;
    c.row = A.row;
    c.column = B.column;
    memset(c.g,0,sizeof(c.g));
    for(int i = 0; i < A.row; ++i)
    {
        for(int k = 0; k < A.column; ++k)
        {
            if(A.g[i][k] != 0)
            {
                for(int j = 0; j < B.column; ++j)
                {
                    c.g[i][j] += A.g[i][k]*B.g[k][j];
                }
            }
        }
    }
    return c;
}

matrix matrix_pow(matrix &A, int n)
{
    matrix temp;
    temp.row = temp.column = A.row;
    memset(temp.g,0,sizeof(temp.g));
    for(int i = 0; i < temp.row; ++i)
        temp.g[i][i] = 1;
       
    while(n)
    {
        if(n % 2 == 1)
            temp = multiply(temp,A);
        A = multiply(A,A);
        n /= 2;
    }
    return temp;
}

int main()
{
//    freopen("input.txt","r",stdin);
    while(scanf("%d %d %d",&n, &m, &K) != EOF)
    {
        if(n == 0 && m == 0 && K == 0) break;
        read_graph();
        a = matrix_pow(a,m);
       
        for(int i = 1; i < a.row; ++i)
        {
            if(i == 1) printf("%lld",a.g[0][i]);
            else printf(" %lld",a.g[0][i]);
        }
        printf("\n");
    }
    return 0;
}
0 0
原创粉丝点击