Challenge: Circle Summation

Subdomeniu: Algebra (algebra)

Scor cont: 80.0 / 80

Submission status: Accepted

Submission score: 1.0

Submission ID: 464735083

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/circle-summation/problem

Cerinta

There are $n$ children, numbered $1,2,\ldots,n$, sitting around a circle in a clockwise manner. The $i$th child has a piece of paper with the number $a_i$ written on it. They play the following game:

- In the $1$st round, the child numbered $i$ increases his number by the sum of the numbers of his neighbors.  
- In the $2$nd round, the child next in clockwise order increases his number by the sum of the numbers of his neighbors.
- In the $3$rd round, the child next in clockwise order increases his number by the sum of the numbers of his neighbors.
- And so on.  

The game ends after $m$ rounds have been played.  

For every $i$, find the numbers that the children end up with if the game starts with child $i$ playing the first round. Since the numbers can be large, output them [modulo](https://en.wikipedia.org/wiki/Modulo_operation) $10^9 + 7$.

Input Format

The first line contains $t$, the number of test cases. $t$ cases follow.  

The first line of each test case contains two space-separated integers $n$ and $m$. The next line contains $n$ integers, the $i$th of which is $a_i$.

Output Format

For each test case, print $n$ lines, each having $n$ integers. The $j$th integer on the $i$th line contains the number that the $j$th child ends up with if the game starts with child $i$ playing the first round.  

Print a blank line after each test case *except the last one*.  

Since the numbers can be large, output them [modulo](https://en.wikipedia.org/wiki/Modulo_operation) $10^9 + 7$.

Constraints

- $1 \le t \le 15$  
- $3 \le n \le 50$  
- $1 \le m \le 10^9$  
- $1 \le a_i \le 10^9$

Cod sursa

// https://www.hackerrank.com/challenges/circle-summation

#include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <unordered_set>

using namespace std;

typedef unsigned long long ullong;

#define MOD_NUM 1000000007ull

class SquareMatrix {
public:
        SquareMatrix(int _size, int _exp)
                : size(_size), exp(_exp) {
                //cout << _size << " " << _exp << endl;
                M = vector< vector<ullong> > (size, vector<ullong>(size, 0));
                orig = vector< vector<ullong> > (size, vector<ullong>(size, 0));
                initCircleSummation();
        }

        void multiply(const vector<ullong> &v, vector<ullong> & output) {
                output = vector<ullong>(v.size(), 0);
                for(int row = 0; row < size; ++row)
                        for(int col = 0; col < size; ++col)
                                output[row] =
                                        (output[row] + (M[row][col] * v[col])%MOD_NUM)
                                        %MOD_NUM;
        }

        void print() {
                for(int row = 0; row < size; ++row) {
                        for(int col = 0; col < size; ++col)
                                printf("%d ", M[row][col]);
                        printf("\n");
                }
                printf("\n");
        }

private:
        void initCircleSummation() {
                for(int index = 1; index < size; index++)
                        orig[index-1][index] = M[index-1][index] = 1;
                M[size-1][0] = M[size-1][1] = M[size-1][size-1] = 1;
                orig[size-1][0] = orig[size-1][1] = orig[size-1][size-1] = 1;
                findExponential(exp);
        }

        void findExponential(int _exp) {

                if(_exp >= 2) {
                        findExponential(_exp/2);
                        multiplyWithItself();

                        if(_exp % 2 == 1)
                                multiplyWithOriginal();
                }
        }
        void multiplyWithItself() {
                vector<vector<ullong> > temp =
                        vector< vector<ullong> > (size, vector<ullong>(size, 0));
                for(int row = 0; row < size; ++row)
                        for(int col = 0; col < size; ++col) {
                                for(int k = 0; k < size; ++k)
                                    temp[row][col] =
                                                (temp[row][col] + (M[row][k] *
                                                                                   M[k][col] ) %MOD_NUM )
                                                % MOD_NUM;
                        }

                for(int row = 0; row < size; ++row)
                        for(int col = 0; col < size; ++col)
                                M[row][col] = temp[row][col];
        }

        void multiplyWithOriginal() {
                vector<vector<ullong> > temp =
                        vector< vector<ullong> > (size, vector<ullong>(size, 0));
                for(int row = 0; row < size; ++row)
                        for(int col = 0; col < size; ++col) {
                                for(int row2 = 0; row2 < size; ++row2)
                                    temp[row][col] =
                                                (temp[row][col] + (M[row][row2] *
                                                                                   orig[row2][col] ) %MOD_NUM )
                                                % MOD_NUM;
                        }
                for(int row = 0; row < size; ++row)
                        for(int col = 0; col < size; ++col)
                                M[row][col] = temp[row][col];
        }

        vector<vector<ullong> > M, orig;
        int size;
        int exp;
};

void print(vector<ullong> &vec, int n) {
        int index = 0;
        for(auto it = vec.begin() + vec.size() - n;
                it != vec.end(); ++it, ++index) {
                printf("%d", *it);
                if(index < vec.size()-1)
                        printf(" ");
        }
        for(auto it = vec.begin();
                it != vec.begin() + vec.size() - n; ++it, ++index) {
                printf("%d", *it);
                if(index < vec.size()-1)
                        printf(" ");
        }
}

void rotateBy1(vector<ullong> &vec) {
        list<ullong> rotated(vec.begin()+1, vec.end());
        rotated.push_back(vec[0]);
        vec.clear();
        vec = vector<ullong>(rotated.begin(), rotated.end());
}

void solveCircleSummation() {
        int nTests;
        scanf(" %d", &nTests);
        for(int test = 0; test < nTests; ++test) {
                int N;
                int mSize;
                scanf(" %d %d", &N, &mSize);

                vector<ullong> vec;
                for(int entry = 0; entry < N; ++entry) {
                        int inp;
                        scanf(" %d", &inp);
                        vec.push_back(inp);
                }

                SquareMatrix sqMat = SquareMatrix(N, mSize);
                int N_1 = mSize%N;
                vector<ullong> finalOut(N, 0);
                for(int entry = 0; entry < N; ++entry) {
                        sqMat.multiply(vec, finalOut);
                        print(finalOut, N_1);
                        printf("\n");
                        N_1 = (N_1 + 1) % N;
                        rotateBy1(vec);
                }
                if(test < nTests -1)
                        printf("\n");
        }
}

int main() {
        solveCircleSummation();
        return 0;
}
HackerRank Algebra – Circle Summation