# My Weblog

## SPOJ DIE HARD

DIEHARD I tried to find out greedy solution but could not come up so trying every possibility and memoization of each state. See more about dynamic programming. The basic idea is that you have to always go to air to increase your chance for survival because its increase the health and armor. We start in air with health increased by 3 and armor increased by 2. After that we have to find out which one, going to water or fire gives maximum survival. A simple Haskell recursive solution which works for small values. We start from funsolve_Air after that we chose the maxiumum value of two functions respectively for water and fire.

funsolve_WF :: Int -> Int -> Int -> Int
funsolve_WF h a cnt
| h <= 0 || a <= 0 = cnt
| otherwise = funsolve_Air h a ( cnt + 1 )

funsolve_Air :: Int -> Int -> Int -> Int
funsolve_Air h a cnt = max ( funsolve_WF ( h + 3 - 5 ) ( a + 2 - 10 ) cnt' ) ( funsolve_WF ( h + 3  - 20 )  ( a + 2  + 5 )  cnt' ) where
cnt' = cnt + 1

*Main> funsolve_Air 20 8 0
5
*Main> funsolve_Air 2 10 0
1
*Main> funsolve_Air 4 4  0
1


Accepted source code in C++.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

int memo[1100][1100] ;

int recurse( int h , int a , int cnt , bool flag )
{
if ( h <= 0 || a <= 0 ) return cnt ;
if ( memo[h][a] ) return memo[h][a] ;
if ( flag ) memo[h][a] = max ( memo[h][a] , recurse ( h + 3 , a + 2 , cnt + 1 , !flag ) ) ;
else
memo[h][a] = max ( memo[h][a] ,  max ( recurse ( h - 5 , a - 10 , cnt + 1 , !flag ) , recurse ( h - 20 , a + 5 , cnt + 1 , !flag ) ) ) ;

return memo[h][a];
}

int main()
{
int n , a , b ;
scanf( "%d", &n );
for(int i = 0 ; i < n ; i++)
{
memset ( memo , 0 , sizeof memo ) ;
scanf("%d%d", &a , &b );
printf("%d\n" , recurse( a , b , -1 ,  1 ));
if( i != ( n - 1 ) ) printf("\n");
}

}



December 11, 2012

## Project Euler 357

Project Euler 357 is easy one. I was trying to solve problem 356 and finally ended up with solving easy problem. Nothing new just sieve of eratosthenes and couple of constraints.
Edit: Finally wrote a Haskell solution. See more discussion on Haskell-Cafe. Compile this code with ghc –make -O2 filename.hs

import Control.Monad.ST
import Data.Array.ST
import Data.Array.Unboxed
import Data.List

prime :: Int -> UArray Int Bool
prime n = runSTUArray $do arr <- newArray ( 2 , n ) True :: ST s ( STUArray s Int Bool ) forM_ ( takeWhile ( \x -> x*x <= n ) [ 2 .. n ] )$ \i -> do
when ( ai  ) $forM_ [ i^2 , i^2 + i .. n ]$ \j -> do
writeArray arr j False

return arr

pList :: UArray Int Bool
pList = prime $10 ^ 8 divPrime :: Int -> Bool divPrime n = all ( \d -> if mod n d == 0 then pList ! ( d + div n d ) else True )$  [ 1 .. truncate . sqrt . fromIntegral  $n ] main = putStrLn . show . sum$ ( [ if and [ pList ! i , divPrime . pred $i ] then ( fromIntegral . pred$ i ) else 0 | i <- [ 2 .. 10 ^ 8 ] ] :: [ Integer ] )

#include<cstdio>
#include<iostream>
#include<vector>
#define Lim 100000001
using namespace std;

bool prime [Lim];
vector<int> v ;

void isPrime ()
{
for( int i = 2 ; i * i <= Lim ; i++)
if ( !prime [i]) for ( int j = i * i ; j <= Lim ; j += i ) prime [j] = 1 ;

for( int i = 2 ; i <= Lim ; i++) if ( ! prime[i] ) v.push_back( i ) ;
//cout<<v.size()<<endl;
//for(int i=0;i<10;i++) cout<<v[i]<<" ";cout<<endl;

}

int main()
{
isPrime();
int n = v.size();
long long sum = 0;
for(int i = 0 ; i < n ; i ++)
{
int k = v[i]-1;
bool f = 0;
for(int i = 1 ; i*i<= k ; i++)
if ( k % i == 0 && prime[ i + ( k / i ) ] )  { f=1 ; break ; }

if ( !f ) sum += k;
}
cout<<sum<<endl;
}


November 7, 2011

## SPOJ 8456. PRIMITIVEROOTS

SPOJ 8456. PRIMITIVEROOTS is related to number theory. Product of primitive roots of p ( prime number ) mod p is equal to 1.The product of all primitive roots of prime p $\not=$ 3 is $\equiv 1$ ( mod p ). History of the theory of numbers By Leonard Eugene Dickson on page 183.This problem is not allowed in Haskell. Accepted C++ code.

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;

bool p[10010];

void prime()
{
for(int i=2 ; i*i <=10000 ; i++ )
if(!p[i])
for(int j = i*i ; j <=10000 ; j += i ) p[j]=1;
//for(int i=2; i <= 20 ; i++) if(!p[i]) cout<<i<<" ";cout<<endl;
}

int main()
{
prime();
int n , t , x=1 ;
for( scanf("%d",&t) ; t>0 ; t--)
{
scanf("%d",&n);
if( n == 3 ) printf("%d:2\n", x++);
else if ( !p[n] ) printf("%d:1\n",x++);
else printf("%d:NOTPRIME\n",x++);
/*if( t != 1 ) printf("\n");*/
}

}


July 17, 2011

## SPOJ 9126. Time to live

SPOJ 9126. Time to live is almost similar to 1437. Longest path in a tree. Find the diameter of tree and maximal needed TTL for network will be radius of tree. Accepted c++ code.

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;

vector<int> V[100100];
int vis[100100],dist[100100],k;
void dfs(int v,int n)
{

vis[v]=1;
dist[v]=n;
for(int u=0;u<V[v].size();u++)
if(!vis[V[v][u]])
dfs(V[v][u],n+1);

}

int main()
{
int n,t1,t2 , t;
for(scanf("%d",&t) ;t > 0 ; t-- )
{
scanf("%d",&n);
for(int i=0;i<n;i++)
V[i].clear(),vis[i]=0;

for(int i=0;i<n-1;i++)
{
scanf("%d%d",&t1,&t2);
V[t1].push_back(t2);
V[t2].push_back(t1);
}

//if(n==2) { cout<<"1\n";continue;}

dist[0]=0;
dfs(0,0);
/* for(int i=0;i<n;i++)
cout<<dist[i]<<" ";
cout<<endl;*/

int node=0;
for(int i=0;i<n;i++)
if(dist[i]>dist[node])
node=i;

memset(vis,0,sizeof(vis));
// cout<<"node"<<node<<endl;

dfs(node,0);

/*for(int i=0;i<n;i++)
cout<<dist[i]<<" ";
cout<<endl;*/

sort(dist,dist+n);
int d = dist[n-1];
if( d & 1 ) cout<< ( d>>1 ) + 1 <<endl;
else cout<< ( d>>1 ) <<endl;
//cout<<dist[n-1]<<endl;

}
}


July 7, 2011

## SPOJ 9122. Diary

SPOJ 9122. Diary is just simulation problem. Only thing we need to consider is ” If the decryption is not possible because there are multiple distances conforming to the rules above, print NOT POSSIBLE instead”. Count all the occurrence of alphabets and find out which one is maximum. If there are more than one alphabets , clearly its impossible to decrypt otherwise assign it ‘E’ and calculate distance and decrypt the string. Accepted c++ code.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

int cnt[30];

int main()
{
int t ;
string s , final ;
for( scanf("%d\n",&t) ; t > 0 ; t-- )
{
memset( cnt , 0 , sizeof cnt );
getline( cin , s );
int len = s.length();
for(int i = 0; i < len ; i++) if ( s[i] >= ' ' ) cnt[s[i]-'A']++ ;

//cout<<s<<endl;
//for(int i=0;i<26;i++) cout<<cnt[i]<<" ";cout<<endl;
//find out most occuring word and this is E
//what if i have more than two words have same occurance

int mx = -1 , ind = -1  ;
for(int i = 0 ; i < 26 ; i++ ) if ( cnt[i] > mx ) mx = cnt[i] , ind = i ;

int c = 0 ;
for(int i = 0 ; i < 26 ; i++) if (cnt[i]==mx ) c++;
if ( c>1 ) { cout<<"NOT POSSIBLE\n" ; continue ;}

int dist =  ( ind - 4 + 26 ) % 26 ;
final = "";
for(int i = 0 ; i < len ; i++)
if (s[i] !=' ') final += ( char ) (  'A' + ( ( s[i] - 'A' - dist + 26 ) % 26 ) ) ;
else final += ' ' ;

cout<<dist<<" "<<final<<endl;

}
}