A better algorithm for a task connected with Exponentiation - algorithm

recently I found an interesting task given in a competition, but without any author solution or explanation how to be solved.
The task consists of the following: The user is given a number N, and has to calculate a^N (on the power of n, not the xor operation), where I can only calculate by multiplying by a, or by a previous result. I should give the smallest number of calculations I should do in order to get calculate a^n.
Example:
N=27
Then the answer is 6:
a^2=a*a
a^3=a^2*a
a^6=a^3*a^3
a^9=a^3*a^6
a^18=a^9*a^9
a^27=a^18*a^9
The limits for N are the following: N<=40000. The time and memory limits are: 2s and 256MB.
What is a good way to solve this task?
Thank you in advance!!!

This is one simple solution but not fast enough..
I wish someone could enhance this by some tweak?
Or for someone who is interested just in solving the problem.
#include<set>
#include<iostream>
using namespace std;
int main(int argc, char** argv)
{
set<int> A, B;
A.insert(1);
int n = atoi(argv[1]), i;
for(i=1; A.find(n) == A.end(); i++) {
for(auto& a : A) for(auto& b : A) B.insert(a + b);
for(auto& c : B) A.insert(c);
}
cout << i << endl;
}
Let's ask the other way..
How far can I know by calculaing n times?
It just doubles every time.
Am I missing something?
That said, only by this one line,
while(pow(2, n)< atoi(argv[1])) n++;
cout << n;
the result can be gained.

Related

Minimizing the distance of pairing points

My problem is as follows:
Given a number of 2n points, I can calculate the distance between all points
and get a symmetrical matrix.
Can you create n pairs of points, so that the sum of the distance of all pairs is
minimal?
EDIT: Every point has to be in one of the pairs. Which means that
every point is only allowed to be in one pair.
I have naively tried to use the Hungarian algorithm and hoped that it may give me an assignment, so that the assignments are symmetrical. But that obviously did not work, as I do not have a bipartite graph.
After a search, I found the Stable roommates problem, which seems to be similar to my problem, but the difference is, that it just tries to find a matching, but not to try to minimize some kind of distance.
Does anyone know a similar problem or even a solution? Did I miss something? The problem does actually not seem that difficult, but I just could not come up with an optimal solution.
There's a primal-dual algorithm due to Edmonds (the Blossom algorithm), which you really don't want to implement yourself if possible. Vladimir Kolmogorov has an implementation that may be suitable for your purposes.
Try network-flow. The max flow is the number of the pairs you want to create. And calculate the min cost of it.
now this isn't a guarantee but just a hunch.
you can find the shortest pair, match them, and remove it from the set.
and recurse until you have no pairs left.
It is clearly sub-optimal. but I have a hunch that the ratio of just how sub-optimal this is to the absolutely optimal solution can be bounded. The hope is to use some sub-modularity argument and bound it to something like (1 - 1 / e) fraction of the global optimal, but I wasn't able to do it. Maybe someone could take a stab at it.
There is a C++ memoization implementation in Competitive Programming 3 as follows (note maximum of N was 8):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
int N, target;
double dist[20][20], memo[1<<16];
double matching(int bitmask)
{
if (memo[bitmask] > -0.5) // Already computed? Then return the result if yes
return memo[bitmask];
if (bitmask == target) // If all students are already matched then cost is zero
return memo[bitmask] = 0;
double ans = 2000000000.0; // Infinity could also work
int p1, p2;
for (p1 = 0; p1 < 2*N; ++p1) // Find first non-matched point
if (!(bitmask & (1 << p1)))
break;
for (p2 = p1 + 1; p2 < 2*N; ++p2) // and pair it with another non-matched point
if (!(bitmask & (1 << p2)))
ans = min(ans, dist[p1][p2]+matching(bitmask| (1 << p1) | (1 << p2)));
return memo[bitmask] = ans;
}
and then the main method (driving code)
int main()
{
int i,j, caseNo = 1, x[20], y[20];
while(scanf("%d", &N), N){
for (i = 0; i < 2 * N; ++i)
scanf("%d %d", &x[i], &y[i]);
for (i = 0; i < 2*N - 1; ++i)
for (j = i + 1; j < 2*N; ++j)
dist[i][j] = dist[j][i] = hypot(x[i]-x[j], y[i]-y[j]);
// use DP to solve min weighted perfect matching on small general graph
for (i = 0; i < (1 << 16); ++i) memo[i] = -1;
target = (1 << (2 * N)) - 1;
printf("Case %d: %.2lf", caseNo++, matching(0));
}
return 0;
}

Optimized way to find if a number is a perfect square

I had a question in my assignment to find whether a number was perfect square or not:
Perfect square is an element of algebraic structure which is equal to
the square of another element.
For example: 4, 9, 16 etc.
What my friends did is, if n is the number, they looped n - 1 times calculating n * n:
// just a general gist
int is_square = 0;
for (int i = 2; i < n; i++)
{
if ((i * i) == n)
{
std::cout << "Yes , it is";
is_square = 1;
break;
}
}
if (is_square == 0)
{
std::cout << "No, it is not";
}
I came up with a solution as shown below:
if (ceil(sqrt(n)) == floor(sqrt(n)))
{
std::cout << "Yes , it is";
}
else
{
std::cout << "no , it is not";
}
And it works properly.
Can it be called as more optimized solution than others?
The tried and true remains:
double sqrt(double x); // from lib
bool is_sqr(long n) {
long root = sqrt(n);
return root * root == n;
}
You would need to know the complexity of the sqrt(x) function on your computer to compare it against other methods. By the way, you are calling sqrt(n) twice ; consider storing it into a variable (even if the compiler probably does this for you).
If using something like Newton's method, the complexity of sqrt(x) is in O(M(d)) where M(d) measures the time required to multiply two d-digits numbers. Wikipedia
Your friend's method does (n - 2) multiplications (worst case scenario), thus its complexity is like O(n * M(x)) where x is a growing number.
Your version only uses sqrt() (ceil and floor can be ignored because of their constant complexity), which makes it O(M(n)).
O(M(n)) < O(n * M(x)) - Your version is more optimized than your friend's, but is not the most efficient. Have a look at interjay's link for a better approach.
#include <iostream>
using namespace std;
void isPerfect(int n){
int ctr=0,i=1;
while(n>0){
n-=i;
i+=2;
ctr++;
}
if(!n)cout<<"\nSquare root = "<<ctr;
else cout<<"\nNot a perfect square";
}
int main() {
isPerfect(3);
isPerfect(2025);
return 0;
}
I don't know what limitations do you have but perfect square number definition is clear
Another way of saying that a (non-negative) number is a square number,
is that its square roots are again integers
in wikipedia
IF SQRT(n) == FLOOR(SQRT(n)) THEN
WRITE "Yes it is"
ELSE
WRITE "No it isn't"
examples sqrt(9) == floor(sqrt(9)), sqrt(10) == floor(sqrt(10))
I'll recommend this one
if(((unsigned long long)sqrt(Number))%1==0) // sqrt() from math library
{
//Code goes Here
}
It works because.... all Integers( & only positive integers ) are positive multiples of 1
and Hence the solution.....
You can also run a benchmark Test like;
I did with following code in MSVC 2012
#include <iostream>
#include <conio.h>
#include <time.h>
#include <math.h>
using namespace std;
void IsPerfect(unsigned long long Number);
void main()
{
clock_t Initial,Final;
unsigned long long Counter=0;
unsigned long long Start=Counter;
Start--;
cout<<Start<<endl;
Initial=clock();
for( Counter=0 ; Counter<=100000000 ; Counter++ )
{
IsPerfect( Counter );
}
Final=clock();
float Time((float)Final-(float)Initial);
cout<<"Calculations Done in "<< Time ;
getch();
}
void IsPerfect( unsigned long long Number)
{
if(ceil(sqrt(Number)) == floor(sqrt(Number)))
//if(((unsigned long long)sqrt(Number))%1==0) // sqrt() from math library
{
}
}
Your code took 13590 time units
Mine just 10049 time units
Moreover I'm using few extra steps that is Type conversion
like
(unsigned long long)sqrt(Number))
Without this it can do still better
I hope it helps .....
Have a nice day....
Your solutions is more optimized, but it may not work. Since sqrt(x) may return the true square root +/- epsilon, 3 different roots must be tested:
bool isPerfect(long x){
double k = round( sqrt(x) );
return (n==(k-1)*(k-1)) || (n==k*k) || (n==(k+1)*(k+1));
}
This is simple python code for finding perfect square r not:
import math
n=(int)(input())
giv=(str)(math.sqrt(n))
if(len(giv.split('.')[1])==1):
print ("yes")
else:
print ("No")

Am I using Dynamic Programming? Matrix chain multiplication in c

Halo I just write code to perform Matrix chain multiplication, which can be solved by Dynamic Programming
http://en.wikipedia.org/wiki/Matrix_chain_multiplication#A_Dynamic_Programming_Algorithm
Here is the code I wrote, which I think is simpler than the one provided by wikipedia. So I doubt am i doing dynamic programming or not?
and I can't figure out the time complexity of my program. Can someone help me to figure the time complexity of this program?
Here's my guess..
the for loop will run n times for each call? if mem is not used..
for each loop, it will then expand into two
if mem is used, it prevent recalculation...
ahhh I can't figure it out, hope someone can help me :-)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <climits>
using namespace std;
int mem[10][10];
int row[10];
int col[10];
int m[10];
#define NUM 4
int DP(int c, int r){
if(mem[c][r] != INT_MAX) return mem[c][r];
if(c == r) return 0;
int min_cost;
for(int j=c; j<r; j++){
min_cost = DP(c, j) + DP(j+1, r) + m[c-1]*m[j]*m[r];
if(min_cost < mem[c][r])
mem[c][r] = min_cost;
}
return mem[c][r];
}
int main(){
for(int i=0; i< 10;i++){
for(int j=0; j<10;j++){
mem[i][j] = INT_MAX;
}
}
int n = NUM; // MAX 4 matrix
int a,b;
for(int i=0; i< NUM+1; i++){
cin >> a;
m[i] = a;
}
cout << "Lowest Cost for matrix multiplicatoin " << DP(1,NUM);
}
The technique you have used is called memoization. Most of the time, you may solve DP problems using memoization with little (or no) overhead.
The complexity of your implementation is just like the original DP solution: O(n^3) (Note: Every cell of mem array should be computed at least once, and each cell takes O(n) time to be computed. Further computation of a cell, does not involve any loop, since it would be a simple lookup.)
See also http://en.wikipedia.org/wiki/Memoization

find minimum step to make a number from a pair of number

Let's assume that we have a pair of numbers (a, b). We can get a new pair (a + b, b) or (a, a + b) from the given pair in a single step.
Let the initial pair of numbers be (1,1). Our task is to find number k, that is, the least number of steps needed to transform (1,1) into the pair where at least one number equals n.
I solved it by finding all the possible pairs and then return min steps in which the given number is formed, but it taking quite long time to compute.I guess this must be somehow related with finding gcd.can some one please help or provide me some link for the concept.
Here is the program that solved the issue but it is not cleat to me...
#include <iostream>
using namespace std;
#define INF 1000000000
int n,r=INF;
int f(int a,int b){
if(b<=0)return INF;
if(a>1&&b==1)return a-1;
return f(b,a-a/b*b)+a/b;
}
int main(){
cin>>n;
for(int i=1;i<=n/2;i++){
r=min(r,f(n,i));
}
cout<<(n==1?0:r)<<endl;
}
My approach to such problems(one I got from projecteuler.net) is to calculate the first few terms of the sequence and then search in oeis for a sequence with the same terms. This can result in a solutions order of magnitude faster. In your case the sequence is probably: http://oeis.org/A178031 but unfortunately it has no easy to use formula.
:
As the constraint for n is relatively small you can do a dp on the minimum number of steps required to get to the pair (a,b) from (1,1). You take a two dimensional array that stores the answer for a given pair and then you do a recursion with memoization:
int mem[5001][5001];
int solve(int a, int b) {
if (a == 0) {
return mem[a][b] = b + 1;
}
if (mem[a][b] != -1) {
return mem[a][b];
}
if (a == 1 && b == 1) {
return mem[a][b] = 0;
}
int res;
if (a > b) {
swap(a,b);
}
if (mem[a][b%a] == -1) { // not yet calculated
res = solve(a, b%a);
} else { // already calculated
res = mem[a][b%a];
}
res += b/a;
return mem[a][b] = res;
}
int main() {
memset(mem, -1, sizeof(mem));
int n;
cin >> n;
int best = -1;
for (int i = 1; i <= n; ++i) {
int temp = solve(n, i);
if (best == -1 || temp < best) {
best = temp;
}
}
cout << best << endl;
}
In fact in this case there is not much difference between dp and BFS, but this is the general approach to such problems. Hope this helps.
EDIT: return a big enough value in the dp if a is zero
You can use the breadth first search algorithm to do this. At each step you generate all possible NEXT steps that you havent seen before. If the set of next steps contains the result you're done if not repeat. The number of times you repeat this is the minimum number of transformations.
First of all, the maximum number you can get after k-3 steps is kth fibinocci number. Let t be the magic ratio.
Now, for n start with (n, upper(n/t) ).
If x>y:
NumSteps(x,y) = NumSteps(x-y,y)+1
Else:
NumSteps(x,y) = NumSteps(x,y-x)+1
Iteratively calculate NumSteps(n, upper(n/t) )
PS: Using upper(n/t) might not always provide the optimal solution. You can do some local search around this value for the optimal results. To ensure optimality you can try ALL the values from 0 to n-1, in which worst case complexity is O(n^2). But, if the optimal value results from a value close to upper(n/t), the solution is O(nlogn)

Travelling Salesman Problem

I am trying to develop a program in C++ from Travelling Salesman Problem Algorithm. I need a distance matrix and a cost matrix. After using all the formulas, i get a new resultant matrix. But I dont understand what that matrix shows.
Suppose the resultant matrix is:
1 2 3
4 5 6
7 8 9
Now I want to know what this matrix shows? Assume I have 3 cities to traverse.
Please tell me the flow. A sample program of this algorithm will be more favorable..
Thank you.
My Program is:
#include<iostream.h>
#include<conio.h>
#include <stdlib.h>
void main()
{
clrscr();
int a,b,c,d,ctr,j,Q=1,K=1 ;
float q0=0.7, p = 0.5 ;
int phe[3][3];
double dist[3][3] , mem[3][3],exp[3][3],eplt[3][3], rnd;
cout<<"enter the iterations, cities , ants ";
cin>>a>>b>>c;
for (int i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
dist[i][j]=(double)rand()/(double)RAND_MAX;
if (i==j)
dist[i][j]=0;
}
}
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
cout<< dist[i][j]<<"\t";
}
cout<<"\n";
}
cout<<"pheromone matrix "<<endl;
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
if (i==j)
phe[i][j]=0;
else
phe[i][j]=1;
}
}
for ( i=0;i<3;i++)
{
for ( j=0;j<3;j++)
{
cout<< phe[i][j]<<"\t";
}
cout<<"\n";
}
cout<< "after iteration "<<endl;
for (i=0;i<3;i++)
{
ctr=0;
for (int k=0;k<3;k++)
{
// mem[i][k]=(rand()%b)+1;
// cout<<"memory"<<mem[i][k]<<"\n";
rnd= (double)rand()/(double)RAND_MAX;
cout<<"hhhhhhh"<<rnd;
if (rnd<=q0)
{
cout<<"Exploitation\n";
eplt[i][ctr] =(p*phe[i][k])+(Q/K);
}
else
{
cout<<"EXPLORATION\n";
eplt[i][ctr]= phe[i][k]/dist[i][k];
}
ctr++;
}
}
for (i=0;i<3;i++)
{
for (int k=0;k<3;k++)
{
cout <<eplt[i][k]<<"\t";
}
cout<<"\n";
}
getch();
}
OUTPUT:
enter the iterations, cities , ants 3
4
4
0 0.003967 0.335154
0.033265 0 0.2172
0.536973 0.195776 0
pheromone matrix
0 1 1
1 0 1
1 1 0
after iteration
hhhhhhh0.949919EXPLORATION
hhhhhhh0.356777EXPLOITATION
hhhhhhh0.356777EXPLOITATION
hhhhhhh0.356777EXPLOITATION
hhhhhhh0.356777EXPLOITATION
hhhhhhh0.356777EXPLOITATION
hhhhhhh0.949919EXPLORATION
First up, I'm guessing when you say My Program you mean The program in the paper since it is basically out of date C++. Standard library headers don't have .h appended, and conio.h is an MS-DOS header - most code that I've seen that uses that comes from Borland Turbo C++. Worth bearing in mind if you're going to try to compile that demo on a modern system.
Next up, what you're looking at is an adjacancy matrix. I don't believe that matrix is part of the output at all; I believe it is part of the model being used, for demonstration purposes. I believe, given you have a pheromone matrix, that what you're looking at here is Ant Colony Optimisation, a probabilistic method of solving the TSP and other problems that can be reduced to it.
From your output, it isn't clear where or how the result is being stored, and since this is homework, I am lazy and you're just asking for an outright answer, I'm not going to read that code. The premise of Ant Colony optimisation is that pheromone trails laid by ants, which walk the graph at random, decay over time (number of iterations). The longer it takes an ant to move along a particular vertex (distance), the more the laid pheromone decays. At this point, ants start to make decisions based on the strength of the laid pheromone along a path. So what happens is ants start to prefer certain routes over others, and continually re-inforce the pheromone along that path.
So, somewhere in there, there must be a matrix like the adjacancy matrix, storing the pheromone levels for each route. Combined with the length of the route, each iteration should detect a rate of decay.
Your input variables a, b, c are never used.
Your variable ctr is used in the exact same incremental way as the variable k of the same loop.
Your phenomone matrix indicates use of an ant colony optimization algorithm, why just not say it in your question ?
Such "iteration" should be, well, iterated, so probably the output you give us (which is not a normal output) is not the definitive solution, rather a provisory result of the algorithm.
In this post, implementation of simple solution is discussed.
Consider city 1 or 0 as the starting and ending point. Since route is
cyclic, we can consider any point as starting point.
Generate all (n-1)! permutations of cities.
Calculate cost of every permutation and keep track of minimum cost
permutation.
Return the permutation with minimum cost.
#include <bits/stdc++.h>
using namespace std;
int main(void){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
int graph[n][n];
for(int i =0;i<n;i++){
for(int j =0;j<n;j++){
scanf("%d",&graph[i][j]);
}
}
vector<int> v;
int s = 0;
for(int i =0;i<n;i++){
if(i!=s){
v.push_back(i);
}
}
int ans = INT_MAX;
do{
int current_pathsum = 0;
int k = s;
for(int i = 0;i<v.size();i++){
current_pathsum += graph[k][v[i]];
k = v[i];
}
current_pathsum += graph[k][s];
ans = min(ans,current_pathsum);
}while(next_permutation(v.begin(),v.end()));
cout<<ans<<endl;
}
}

Resources