Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Matrix Expo and Mo's Algorithm #1022

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions Matrix Expo/matrix-expo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
Matrix Exponentiation. If the problem can be solved with DP but constaints are high.

ai = bi (for i <= k)
ai = c1*ai-1 + c2*ai-2 + ... + ck*ai-k (for i > k)

Taking the example of Fibonacci series, K=2
b1 = 0, b2=1
c1 = 1, c2=1

a = 0 1 1 2 ....
This way you can find the 10^18 fibonacci number%MOD.

I have given a general way to use it. The program takes the input of B and C matrix.
Steps for Matrix Expo
1. Create vector F1 : which is the copy of B.
2. Create transpose matrix (Learn more abput it on the internet)
3. Perform T^(n-1) [transpose matrix to the power n-1]
4. Multiply with F to get the last matrix of size (1xk). The first element of this matrix is the required result.

*/


#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define ull unsigned long long
#define endl '\n'
#define pb push_back
#define mp make_pair
#define trace1(x) cout<<#x<<": "<<x<<endl
#define trace2(x, y) cout<<#x<<": "<<x<<" | "<<#y<<": "<<y<<endl
#define trace3(x, y, z) cout<<#x<<":" <<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl
#define trace4(a, b, c, d) cout<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<endl
#define trace5(a, b, c, d, e) cout<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<< ": "<<e<<endl
#define trace6(a, b, c, d, e, f) cout<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<< ": "<<e<<" | "<<#f<<": "<<f<<endl
#define traceloop(x,a) {for(ll i=0;i<x;i++) cout<<a[i]<<" "; cout<<endl;}
#define MOD 1000000000
ll ab(ll x) {return x>0LL?x:-x;}
ll k;
vector<ll> a,b,c;

//To multiply 2 matrix
vector<vector<ll> > multiply(vector<vector<ll> > A, vector<vector<ll> > B)
{
vector<vector<ll> > C(k+1,vector<ll>(k+1));
for(int i=1; i<=k; i++){
for(int j=1; j<=k; j++){
for(int z=1; z<=k; z++){
C[i][j] = (C[i][j]+ (A[i][z]*B[z][j])%MOD)%MOD;
}
}
}
return C;
}

//computing power of a matrix
vector<vector<ll> > power(vector<vector<ll> > A, ll p)
{
if(p==1)
return A;
if(p%2==1)
return multiply(A,power(A,p-1));
else{
vector<vector<ll> > X = power(A,p/2);
return multiply(X,X);
}

}

//main function
ll ans(ll n)
{
if(n==0)
return 0;
if(n<=k)
return b[n-1];
//F1
vector<ll> F1(k+1);
for(int i=1; i<=k; i++)
F1[i]=b[i-1];

//Transpose matrix
vector<vector<ll> > T(k+1,vector<ll>(k+1));
for(int i=1; i<=k; i++){
for(int j=1; j<=k; j++){
if(i<k){
if(j==i+1)
T[i][j]=1;
else
T[i][j]=0;
continue;
}
T[i][j]=c[k-j];
}
}
//T^n-1
T=power(T,n-1);

// T*F1
ll res=0;
for(int i=1; i<=k; i++)
{
res= (res + (T[1][i]*F1[i])%MOD)%MOD;
}
return res;
}




int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;
cin>>t;
ll i,j,x;
while(t--)
{
cin>>k;
for(i=0; i<k; i++)
{
cin>>x;
b.pb(x);
}
for(i=0; i<k; i++)
{
cin>>x;
c.pb(x);
}
cin>>x;
cout<<ans(x)<<endl;
b.clear();
c.clear();
}
return 0;
}
1 change: 1 addition & 0 deletions Misc./Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
These are some basic codes which does not fall under any category but you should look at them once.
25 changes: 25 additions & 0 deletions Misc./decimal_to_m-ary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//Converting decimal number to m-ary number.
#include<bits/stdc++.h>
using namespace std;

char a[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

string tenToM(int n, int m)
{
int temp=n;
string result="";
while (temp!=0)
{
result=a[temp%m]+result;
temp/=m;
}
return result;
}

int main()
{
int n = 15;
int m = 8;
string str = tenToM(n,m);
cout<<str;
}
24 changes: 24 additions & 0 deletions Misc./m-ary_to_decimal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Convert an m-ary number to decimal number.
#include<bits/stdc++.h>
using namespace std;

string num="0123456789ABCDEF";
int mToTen(string n, int m)
{
int multi=1;
int result=0;
for (int i=n.size()-1;i>=0;i--)
{
result+=num.find(n[i])*multi;
multi*=m;
}
return result;
}

int main()
{
string str = "FF";
int m = 16;
int ans = mToTen(str,m);
cout<<ans;
}
159 changes: 159 additions & 0 deletions Mo's Algorithm/Distinct_elements_in_range.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
Distinct elements in subarray using Mo’s Algorithm
Approach :
1. Sort all queries in a way that queries with L values from 0 to \sqrt(n) - 1 are put together, then all queries from \sqrt(n) to 2*\sqrt(n) - 1, and so on. All queries within a block are sorted in increasing order of R values.
2. Initialize an array freq[] of size 10^6 with 0 . freq[] array keep count of frequencies of all the elements in lying in a given range.
3. Process all queries one by one in a way that every query uses number of different elements and frequency array computed in previous query and stores the result in structure.
4. Let ‘curr_Diff_element’ be number of different elements of previous query.
-Remove extra elements of previous query. For example if previous query is [0, 8] and current query is [3, 9], then remove a[0], a[1] and a[2]
-Add new elements of current query. In the same example as above, add a[9].
5. Sort the queries in the same order as they were provided earlier and print their stored results
*/
#include <bits/stdc++.h>
using namespace std;

// Used in frequency array (maximum value of an
// array element).
const int MAX = 1000000;

// Variable to represent block size. This is made
// global so compare() of sort can use it.
int block;

// Structure to represent a query range and to store
// index and result of a particular query range
struct Query {
int L, R, index, result;
};

// Function used to sort all queries so that all queries
// of same block are arranged together and within a block,
// queries are sorted in increasing order of R values.
bool compare(Query x, Query y)
{
// Different blocks, sort by block.
if (x.L / block != y.L / block)
return x.L / block < y.L / block;

// Same block, sort by R value
return x.R < y.R;
}

// Function used to sort all queries in order of their
// index value so that results of queries can be printed
// in same order as of input
bool compare1(Query x, Query y)
{
return x.index < y.index;
}

// calculate distinct elements of all query ranges.
// m is number of queries n is size of array a[].
void queryResults(int a[], int n, Query q[], int m)
{
// Find block size
block = (int)sqrt(n);

// Sort all queries so that queries of same
// blocks are arranged together.
sort(q, q + m, compare);

// Initialize current L, current R and current
// different elements
int currL = 0, currR = 0;
int curr_Diff_elements = 0;

// Initialize frequency array with 0
int freq[MAX] = { 0 };

// Traverse through all queries
for (int i = 0; i < m; i++) {

// L and R values of current range
int L = q[i].L, R = q[i].R;

// Remove extra elements of previous range.
// For example if previous range is [0, 3]
// and current range is [2, 5], then a[0]
// and a[1] are subtracted
while (currL < L) {

// element a[currL] is removed
freq[a[currL]]--;
if (freq[a[currL]] == 0)
curr_Diff_elements--;

currL++;
}

// Add Elements of current Range
// Note:- during addition of the left
// side elements we have to add currL-1
// because currL is already in range
while (currL > L) {
freq[a[currL - 1]]++;

// include a element if it occurs first time
if (freq[a[currL - 1]] == 1)
curr_Diff_elements++;

currL--;
}
while (currR <= R) {
freq[a[currR]]++;

// include a element if it occurs first time
if (freq[a[currR]] == 1)
curr_Diff_elements++;

currR++;
}

// Remove elements of previous range. For example
// when previous range is [0, 10] and current range
// is [3, 8], then a[9] and a[10] are subtracted
// Note:- Basically for a previous query L to R
// currL is L and currR is R+1. So during removal
// of currR remove currR-1 because currR was
// never included
while (currR > R + 1) {

// element a[currL] is removed
freq[a[currR - 1]]--;

// if ocurrence of a number is reduced
// to zero remove it from list of
// different elements
if (freq[a[currR - 1]] == 0)
curr_Diff_elements--;

currR--;
}
q[i].result = curr_Diff_elements;
}
}

// print the result of all range queries in
// initial order of queries
void printResults(Query q[], int m)
{
sort(q, q + m, compare1);
for (int i = 0; i < m; i++) {
cout << "Number of different elements" <<
" in range " << q[i].L << " to "
<< q[i].R << " are " << q[i].result << endl;
}
}

// Driver program
int main()
{
int a[] = { 1, 1, 2, 1, 3, 4, 5, 2, 8 };
int n = sizeof(a) / sizeof(a[0]);
Query q[] = { { 0, 4, 0, 0 }, { 1, 3, 1, 0 },
{ 2, 4, 2, 0 } };
int m = sizeof(q) / sizeof(q[0]);
queryResults(a, n, q, m);
printResults(q, m);
return 0;
}
Loading