using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace rvip_5
{
    public class Matrix
    {
        private readonly int[,] data;
        public int Size { get; }

        public Matrix(int size)
        {
            Size = size;
            data = new int[size, size];
            FillRandom();
        }

        public Matrix(int[,] data)
        {
            this.data = data;
            Size = data.GetLength(0);
        }

        public int GetElement(int row, int col)
        {
            return data[row, col];
        }

        public void SetElement(int row, int col, int value)
        {
            data[row, col] = value;
        }

        private void FillRandom()
        {
            Random random = new Random();
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    data[i, j] = random.Next(10); // Случайные числа от 0 до 9
                }
            }
        }

        public Matrix MultiplySequential(Matrix other)
        {
            if (Size != other.Size)
            {
                throw new ArgumentException("Матрицы должны быть одинакового размера.");
            }

            int[,] resultData = new int[Size, Size];
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    for (int k = 0; k < Size; k++)
                    {
                        resultData[i, j] += data[i, k] * other.data[k, j];
                    }
                }
            }
            return new Matrix(resultData);
        }

        public Matrix MultiplyParallel(Matrix other, int numThreads)
        {
            if (Size != other.Size)
            {
                throw new ArgumentException("Матрицы должны быть одинакового размера.");
            }

            int[,] resultData = new int[Size, Size];
            Task[] tasks = new Task[numThreads];
            int rowsPerThread = Size / numThreads;

            for (int i = 0; i < numThreads; i++)
            {
                int startRow = i * rowsPerThread;
                int endRow = (i == numThreads - 1) ? Size : (i + 1) * rowsPerThread;
                tasks[i] = Task.Run(() =>
                {
                    for (int row = startRow; row < endRow; row++)
                    {
                        for (int col = 0; col < Size; col++)
                        {
                            for (int k = 0; k < Size; k++)
                            {
                                resultData[row, col] += data[row, k] * other.data[k, col];
                            }
                        }
                    }
                });
            }

            Task.WaitAll(tasks);
            return new Matrix(resultData);
        }

        public override string ToString()
        {
            string result = "";
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    result += data[i, j] + " ";
                }
                result += "\n";
            }
            return result;
        }
    }
}