Counting How Many Numbers In a Range With Specific Property

Intended Problem : LightOj 1140
The problem Asks to output The number of 0’s to be write in range [A,B] inclusive,,,

Okay, The strategy to solve this kind of problem is Simple , Function…

Let F(N) -> be a function which returns the number of 0’s in range [1,N] .( we keep 0 as a special case.)
Then The number of 0’s in range [A,B] = F[B] – F[A-1]

Now only problem remains how to calculate values of F(N) efficiently…

Let string y = "decimal representation of N"
y = "101" if N  = 101

We iterate through the y..
The first digit -> 1
So we can place [0,1] , not more than that.
We declare a variable upto = Which far I can go in this given condition. The condition will be see soon,,

So , ->>> We put 0 in the first position. Go to the next digit..
Can you tell ,which digits I can place in 2nd position ???
0 ?
Not exactly … As We started from 0, and whatever I put in the 2nd position ,It will remain smaller Than N..
This is the condition…. So I need a comparator to tell me whether The I can [0,9] or to the certain limit..
This is done using a bool variable …

low = (low || d < y[i]-'0')

if low == true: d in range [0,9]
else d in range[0,y[i]-'0']

This value is proceded to the next stage..

Again ,One more information is needed to to be propagated. That is Is The number is valid..
Like Putting 0 in the first place doesn’t make any valid representation of the Number…
So we wipe out this chances…
Putting A variable…. prv0
This value is true if we placed valid digits [1,9] in some left digits.
and false otherwise.

Again , We need a counter function, That counts ,how many number can be created if we place d in the i’th place…
This is simple ….

N = 167
how many Number can be created which is <= N && starts with 1 .... this is 68 [100,167]
how many Number can be created which is <= N && starts with 0 .... this is 68 [000,99]

Is it clear ???

Now The solution:::

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

/*------- Constants---- */
#define LMT				100
#define ll				long long
#define ull				unsigned long long
#define MOD				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(ll &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/


string y;
ll dp[11][2][2];

ll cnt ( int inx, int low, int prv0)
{
	if(prv0 == 0) return 0;
	ll r = 0 ;
	for (int i = inx ;  i < y.length() ; i ++ ) {
		r = 10 * r + (low ? 9 : y[i]-'0');
	}
	return r+1;
}


ll cal(int inx , int low , int prv0)
{
	if(inx == y.length()) return 0;

	if(dp[inx][low][prv0] !=-1 ) return dp[inx][low][prv0];
	
	int up = (low ? 9 : y[inx]-'0');
	
	ll r = 0;
	for (int d = 0 ; d <= up ; d ++ ) {

		r += cal(inx+1, (low || (d < y[inx]-'0')) , prv0 || d);

		if(d == 0) r += cnt (inx+1, (low || (d < y[inx]-'0')) , prv0 || d);
	}
	return dp[inx][low][prv0] = r;
}

int main()
{
	ll tc ,cs =0 ;
	ll a , b ;
	sc(tc);
	while (tc -- ) {
		sc(a);
		sc(b);
		ms(dp, -1);
		ll k1 = 0;
		if(a-1>=0 )
		{
			ll p = a-1;
			y.clear();
			while(p){
				y.push_back(p%10+'0');
				p/=10;
			}
			reverse(y.begin(), y.end());
			k1 = cal(0,0,0);
		}
		ll p = b;
		y.clear();
		while (p) {
			y.push_back(p%10+'0'); p/=10;
		}
		reverse(y.begin(), y.end());
		ms(dp, -1);
		ll k2 = cal(0, 0, 0);
		if(a == 0) k2 ++;
		printf("Case %lld: %lld\n" ,++cs, k2 - k1);
	}
	return 0;
}

In my code, call function is the main generator, helper cnt function ..
Using DP , avoids same calculation..
This occurs as overlapping sub-problems..

N = 489
cal(0,0,0)
-> cal(1,1,0) , Put 0 in the 1st place
-> cal(1,1,1) ,Put 1 in the first place
-> cal(1,1,1),Put 2 in the first Place
-> cal(1,1,1) ,Put 3 in the first place
-> cal(1,0,1) ,Put 4 in the first Place

So we memoize the result and write a recursive dp solution.
We just needed to store The value for 0 , we place a condition on d , then add to it

Second Problem : SPOJ MDIGITS
The only change is that we will need to store all the digits, not for only 0’s

Here is The code:


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

/*------- Constants---- */
#define LMT                     15
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

string y;
struct W  {
	int A[10];
	W(){ms(A, 0);}
	void show(){
		FOR(i, 10) printf("%5d" , A[i]);
		printf("\n");
	}
};

W dp[20][2][2];
W EMPTY;
bool vis[20][2][2];

int cnt( int index , int low , int ZERO)
{
	
	if(ZERO == 0) return 0;
	
	int sum = 0 ;
	
	for (int i = index ; i < y.length() ; i ++ ) {
		
		sum = 10 * sum + (low ? 9 : y[i] -'0');
		
	}
	
	return sum + 1;
}

W cal(int index , int low, int ZERO)
{
	
	if(index == y.length() ) return EMPTY;
	
	if(vis[index][low][ZERO] ) return dp[index][low][ZERO];

	W r;
	
	int upTo = (low ? 9: y[index] - '0');

	for (int d = 0 ; d <= upTo ; d ++ ) {
		
		W t = cal(index + 1 , low || d < y[index] -'0' , ZERO || d) ;

		int h =cnt (index + 1, low || d < y[index] -'0' , ZERO || d );
		
		for (int i = 0; i < 10 ; i ++ ) r.A[i] += t.A[i];
		
		r.A[d] += h ;
	}
	vis[index][low][ZERO] = true;
	return dp[index][low][ZERO] = r;
}



int main(void){
	
	for(int a, b; scanf("%d %d", &a, &b) == 2 && (a || b); ){

		if(a>b) swap(a, b);
		ms(dp, 0);
		ms(vis, false);
		y = to_string(a-1);
		W k = cal(0, 0, 0);
		ms(dp, 0);
		ms(vis , false);
		y  = to_string(b);
		W k2  = cal(0 , 0, 0);

				
		for (int i = 0; i < 10; i ++ ) {
			if(i) printf(" ");
			printf("%d",k2.A[i] - k.A[i]);
		}
		printf("\n");
		
	}
	return 0;
}

Another Example :
Given A range [A,B],
Digit Product of a number if the multiplication of all the digits of a number ,
DigitProduct(123) = 1 * 2 * 3 = 6
DigitProduct(1021) = 1 * 0 * 2 * 1 = 0

So you need to summation all the DigitProducts in the range [A,B]

Try To figure it out ??

KMP , Minimum Length of a Repeated String

KMP algorithm quickly finds the minimum length of a substring which is repeated N >=1 times to make the whole string..
An example :
S : ababab
S can be writen as ab * ab * ab where * means concatenation.
So minimal length is 2(ab)

Another example :
S : abababab
S can be writen as abab * abab but which gives a length of 4,,
But S can also be written as ab * ab *ab * ab which gives result 2…

Another :
S : prime
There is no way we can fragment it,, Minimal length = 5

This is the question
Now How we can use kmp to compute minimal length

This will be clear at with this discussion:

S : abcabc

We find it’s Prefix_function

S : a b c a b c
Pi: 0 0 0 1 2 3

Okay : Another

S : a b a b a b
Pi: 0 0 1 2 3 4

Another :

S : a a a a
Pi: 0 1 2 3

Another :

S : a b c d a b c a b c d
Pi: 0 0 0 0 1 2 3 1 2 3 4

From this examples,,, You can see that , For a repeated String , The last entries are 1,2,3,… increasing by 1
For second example :
The last value of prefix table = 4..
Now If it is a repeated string than , It’s minimal length would be 2. (6(string length) – 4) , Now how many time it is concatenated ?
string_length / minimal_length

Furthur checking :

if( minimal_length * times == string_length) :
      "YES, IT's A Repeated String" and Minimal Length = minimal_length
else :
      Minimal Length = string_length

This Method Can be used to solve UVA – 10298
This only requires to find how many times…the string is concatenated??

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

/*------- Constants---- */
#define LMT                     1000006
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define msg(x)			  cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

char P[LMT];
int pi[LMT];

int  prefix_function(char pattern[] , int psize)
{
	
	pi[0] = 0;
	for(int i = 1; i < psize; i ++ ) {
		
		int j = pi[i-1];
		
		while (j > 0 && pattern[j] != pattern[i] ) {
			
			j  = pi[j-1];
		}
		if( pattern[i] == pattern[j ] ) ++ j;
		pi[i ] = j ;
	}
	
	return pi[psize - 1];
}

int main()
{
	
	
	while (scanf("%s",P )) {
		if(P[0] =='.') break;
		int l = (int) strlen(P);
		int k = prefix_function(P, l);
		int in = l - k;
		int N = l / in;
		
		if( in * N == l ) {
			printf("%d\n", N);
		}
		else printf("1\n");
	}
	return 0;
}

Another Hard(:P) Problem That requires this Technique along with DP..
UVA – 11022

This is a dp problems . Where sub-problems are the sub-strings…

In dp table , we store minimum cost of substring S[i...j]

for every substring S[i...j],  We can check if it's a repeated string or not ,.
If it is :
       L = minimum length of repeated string
       dp[i][j] =  minimum cost for minimum repeated string( S[i,...., L-1])
else : 
      //we partition the substring into two substring
      int iMin = inf;
      for(int k = i; k &lt;j ; k ++ ) {
             int t = cost(i,k) + cost(k+1,j)
             iMin = min(iMin , t)
      }
//Save the value in dp Table

Here is the code


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

/*------- Constants---- */
#define LMT				100
#define ll				long long
#define ull				unsigned long long
#define mod				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

string S;
int dp[LMT][LMT];

int prefix_function(string s)
{
	int pi[LMT];
	pi[0] = 0;
	for (int i = 1 ; i < s.length() ; i ++ ) {
		int j = pi[i-1];
		while (j > 0 && s[i] != s[j])  {
			j  = pi[j-1];
		}
		if(s[i] == s[j] ) ++j;
		pi[i] = j;
	}
	int in = s.length() - pi[s.length()-1];
	int N = s.length()/ in;
	if(in*N == s.length() ) {
		return in;
	}
	else return s.length();
	
}
int cal(int i , int j)
{
	if( i == j ) {
		return 1;
	}
	
	if(dp[i][j] !=-1 ) return dp[i][j];
	
	int lengthOfRepeatedSequence = prefix_function(S.substr( i , j - i + 1) );
	if(lengthOfRepeatedSequence == j-i+1){
		int iM = inf;
		for (int  k =  i ; k < j ; k ++ ) {
			int t = cal(i , k) + cal( k + 1 , j );
			if( t < iM) iM = t;
		}
		dp[i][j] = iM;
	}
	else {
		dp[i][j] = cal(i , i + lengthOfRepeatedSequence - 1);
	}
	
	
	return dp[i][j];
}
int main()
{
	
	while (cin >> S ) {
		if(S.compare("*") == 0 ) break;
		ms(dp, -1);
		int p = cal(0 , S.length() -1) ;
		printf("%d\n" , p);
	}
	
	return 0;
}

LightOJ – 1258

Approach : KMP

Okay ? How to solve this using KMP…
It’s not so obvious to apply kmp for a beginner.

1. Reverse The input String ,,,
2. Find The longest Prefix of Reverse String which is a suffix of The whole Input

Example:
Input A: abcc
Rev B: ccba

Now to make pallindrome.. The reverse String need to be equal. But So simply the number of addition of character needed is <len

Like : pqrs , we just add rqp end of the string and get a pallindrome

Now For the first Input : the pallindrome is : abccba..
Addition is less than the len-1 , So just addition of 2 character ( b , a )

We can see that , The length of the prefix of B which is a suffix of A , is 2(cc)
We don't need to repeat this all character at all, because they are already in the string in reversed positon
SO we need to add the character which is not the part of the input string

Given S, search for reverse(S) in S using KMP. The state at the end will be the length of the longest prefix of reverse(S) that matches a suffix of S.

Now writing Prefix_function
As every Thing in C/C++ , Array has 0-based Index, The following implementation

void compute_prefix_function(char pattern[], int psize){
    int k = -1;
    int i = 1;
    pi[0] = k; // pi stores the prefix_value
    for (i = 1; i < psize; i++) {
        while (k >=0 && pattern[k+1] != pattern[i])
            k = pi[k];
        if (pattern[i] == pattern[k+1])
            k++;
        pi[i] = k;
    }
}

Now the task is to find the length of longest prefix which is suffix of T ,
This is just like KMP matcher . We need to find where the pointer in Pattern remains when we are at end of the Text


int kmp(char target[], int tsize, char pattern[], int psize){
    int i, k;
    compute_prefix_function(pattern, psize);
    k = -1;
    for (i=0; i<tsize; i++) {
        while (k>=0 && pattern[k+1]!=target[i]){
            k = pi[k];
        }
        if (target[i] == pattern[k+1]){
            k++;
        }
    
    }
    return k;
}

Finally The whole code :


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

/*------- Constants---- */
#define LMT				1000006
#define ll				long long
#define ull				unsigned long long
#define MOD				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

char inpStr[LMT] , revInpStr[LMT];

int pi[LMT];
void compute_prefix_function(char pattern[], int psize){
	int k = -1;
	int i = 1;
	pi[0] = k; // pi stores the prefix_value
	for (i = 1; i < psize; i++) {
		while (k >=0 && pattern[k+1] != pattern[i])
			k = pi[k];
		if (pattern[i] == pattern[k+1])
			k++;
		pi[i] = k;
	}
}

int kmp(char target[], int tsize, char pattern[], int psize){
	int i, k;
	compute_prefix_function(pattern, psize);
	k = -1;
	for (i=0; i<tsize; i++) {
		while (k>=0 && pattern[k+1]!=target[i]){
			k = pi[k];
		}
		if (target[i] == pattern[k+1]){
			k++;
		}
		
	}
	return k;
}



int main()
{
	int tc, cs =0 , len ;
	sc(tc);
	while (tc -- ) {
		
		gets(inpStr);
		len = (int) strlen(inpStr);
		strcpy(revInpStr, inpStr);
		reverse(revInpStr , revInpStr + len );
		
		int k = kmp(inpStr, len , revInpStr , len);
		printf("Case %d: %d\n" , ++cs , len + len - k - 1 );
	}
	return 0;
}

LightOj – 1396 – Palindromic Numbers (III) , Spoj Pallin

Approach : Greedy , String ,Pallindrome ..

Abridge Statement : Given A string (|s| <= 10^5 ) , You Have to output minimum possible palindromic number which is greater than the given number.

Idea :
1. For a pallindrome String , if we fix the first half , then last half is already selected...
2. To find the minimum possible pallindrome, We first check , if the given string mirrored about it's middle position than it creates bigger pallindrome or not.
S = "123312"
If we mirror the first half , then it creates , 123321 , which is greater than the given string
So this case we can handle.
Now if S= 12312 , This will create 12321 , which is bigger than the given string ,,

I think you understood how to handle odd & even length ...

3. If The mirrored String is small Then we need to derive some method

Let's look S = 1567
What's its next Pallindrome : 1661 ...
How ???

Ok if we update the most significant digit, then It will create bigger pallindrome , No doubt, but not always the minimum possible . To find the minimum possible, We need to update the least significant digits... As I said , The first half determines the second half, So the least updating Position is the middle element.

How to find this pivot element ??
This is easy . in 0 based index, Its index = (len - 1) /2;

so ,we start from the least significant digit to most significant digit,,

Ok , we want to update the least significant digit, Increase its value by 1, Now
Case 1 : if the digit is 9, then We update it to 0, carry to make 1 ,for the later significant digit
Case 2: If the digit is not 9 , increase it by 1 , and note its position(pos ) ,,.

To build The output string,

 
for all i < pos : 
        out[i] = out[len-1-i]  = str[i]
out[pos] = out[len-1-pos] = str[i] + 1;
for i = pos + 1 to i < len -1 - pos  :
       out[i] = '0';

Is everyThing done ??
Not really.
Two special case :
1 :

 
 If |S| = 1 ,: 
       if(S[0] < 9) : out[0] = S[0]+1;
       else :
             out[0] = '1'; out[1]='1'

2. If all the digits are 9,
Think . 999,
What should be the answer. 1001

Think this case and you will get it..

Complete Solution :

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

/*------- Constants---- */
#define LMT				100005
#define ll				long long
#define ull				unsigned long long
#define mod				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/


char str[LMT];
char out[LMT];

int main()
{
	
	
	int tc,cs = 0;
	sc(tc);
	while (tc -- ) {
		
		scanf("%s",str);
		int len = 0 ;
		bool flag = true;
		
		for( ; str[len] ; len ++ ){
			if( str[len] !='9') {
				flag = false;
			}
		}
		
		printf("Case %d: ",++cs);
		
		if(len == 1) {
			if(str[0] <'9' )printf("%c\n" ,str[0] +  1);
			else printf("11\n");
			continue;
		}
		
		if(flag == true ){
			printf("1");
			for(int i = 1; i < len ; i ++) printf("0");
			printf("1\n");
			continue;
		}
		else {
			
			out[len] = '\0';
			
			bool isbig=true , iseq = 1;
			for(int i = (len - 1)/2 ; i >=0  ;i -- ){
				if(str[i]!= str[len-1-i]) {
					isbig = str[i] > str[len-1-i];
					iseq = 0;
					break;
				}
				if(str[i] != str[len - 1 - i ]) iseq = 0;
			}
			
			if(isbig && iseq == 0) {
				for(int i = 0 ; i <= (len - 1)/2 ;i ++ ) out[i] = out[len-1-i] = str[i];
				printf("%s\n",out);
				continue;
			}
			
			
			int ink , pos = 0;
			for(int i = (len-1)/2 ; i >=0 ; i -- ) {
				
				if( str[i] !='9') {
					ink = str[i] +1 ;
					pos = i ;
					flag = true;
					break;
				}
			}
			
			
			
			for(int i = 0 ; i < pos ; i ++ ) out[i] = out[len-1-i] = str[i];
			out[pos]= out[len -1 - pos]  = ink;
			for(int i = pos + 1; i < len -1 - pos ; i ++ ) out[i] = '0';
			
			printf("%s\n",out);
			
		}
		
	}
	return 0;
}


Uva – 11297 – Census

Approach : Segment Tree , Sqrt-Decomposition..

First Solution :

This is typical 2D segment tree problem. Just write the code correctly and good enough to get AC
I used two array , One to store Maximum , One to Minimum ..


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

/*------- Constants---- */
#define LMT				605
#define ll				long long
#define ull				unsigned long long
#define mod				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

int t[4*LMT][4*LMT];
int p[4*LMT][4*LMT];
int a[LMT][LMT];
int m , n ;
void build_y (int vx, int lx, int rx, int vy, int ly, int ry) {
	if (ly == ry)
		if (lx == rx){
			t[vx][vy] = a[lx][ly];
			p[vx][vy] = a[lx][ly];
		}
			
		else {
			t[vx][vy] = max(t[vx*2][vy] , t[vx*2+1][vy] );
			p[vx][vy] = min(p[vx*2][vy] , p[vx*2+1][vy] );
		}
	
		else {
			int my = (ly + ry) / 2;
			build_y (vx, lx, rx, vy*2, ly, my);
			build_y (vx, lx, rx, vy*2+1, my+1, ry);
			t[vx][vy] = max(t[vx][vy *2] , t[vx][vy *2 + 1]);
			p[vx][vy] = min(p[vx][vy *2] , p[vx][vy *2 + 1]);
		}
}

void build_x (int vx, int lx, int rx) {
	if (lx != rx) {
		int mx = (lx + rx) / 2;
		build_x (vx*2, lx, mx);
		build_x (vx*2+1, mx+1, rx);
	}
	build_y (vx, lx, rx, 1, 0, m-1);
}


void update_y (int vx, int lx, int rx, int vy, int ly, int ry, int x, int y, int new_val) {
	if (ly == ry) {
		if (lx == rx){
			t[vx][vy] = new_val;
			p[vx][vy] = new_val;
		}
		else {
			t[vx][vy] = max(t[vx*2][vy] , t[vx*2+1][vy] );
			p[vx][vy] = min(p[vx*2][vy] , p[vx*2+1][vy] );
		}
		
	}
	else {
		int my = (ly + ry) / 2;
		if (y <= my) update_y (vx, lx, rx, vy*2, ly, my, x, y, new_val);
		else update_y (vx, lx, rx, vy*2+1, my+1, ry, x, y, new_val);
		
		t[vx][vy] = max(t[vx][vy *2] , t[vx][vy *2 + 1]);
		p[vx][vy] = min(p[vx][vy *2] , p[vx][vy *2 + 1]);
	}
}

void update_x (int vx, int lx, int rx, int x, int y, int new_val) {
	if (lx != rx) {
		int mx = (lx + rx) / 2;
		if (x <= mx) update_x (vx*2, lx, mx, x, y, new_val);
		else update_x (vx*2+1, mx+1, rx, x, y, new_val);
	}
	update_y (vx, lx, rx, 1, 0, m-1, x, y, new_val);
}


ii query_y (int vx, int vy, int tly, int try_, int ly, int ry) {
	
	if (ly > ry) return ii(-1,inf );
	
	if (ly == tly && try_ == ry) return ii( t[vx][vy] ,p[vx][vy]);
	
	int tmy = (tly + try_) / 2;
	
	ii r1 = query_y (vx, vy*2, tly, tmy, ly, min(ry,tmy));
	ii r2 = query_y (vx, vy*2+1, tmy+1, try_, max(ly,tmy+1), ry);
	
	return ii( max(r1.first , r2.first) , min(r1.second, r2.second)) ;
	
}

ii query_x (int vx, int tlx, int trx, int lx, int rx, int ly, int ry) {
	if (lx > rx)
		return ii(-1,inf );
	if (lx == tlx && trx == rx)
		return query_y (vx, 1, 0, m-1, ly, ry);
	int tmx = (tlx + trx) / 2;
	
	ii r1 = query_x (vx*2, tlx, tmx, lx, min(rx,tmx), ly, ry);
	ii r2 = query_x (vx*2+1, tmx+1, trx, max(lx,tmx+1), rx, ly, ry);
	
	return ii( max(r1.first , r2.first) , min(r1.second, r2.second)) ;
}

int val ;

int main()
{
	
	
	

	int  q ;
	sc(n); sc(m);
	FOR(i , n) FOR(j , m) sc(a[i][j]);
	
	
	build_x(1, 0 , n-1);
	
	sc(q);
	
	char ch ;
	int x1,  x2 , y1 , y2;
	while (q -- ) {
		do {
			ch = gc();
		} while (ch =='\n'||ch =='\0');
		
		if(ch == 'q') {
			sc(x1) ; sc(y1) ;sc(x2);sc(y2);
			x1 -- , y1 -- ,x2 -- , y2 --;
			ii r = query_x( 1, 0 , n -1 , x1 , x2 , y1 , y2);
			printf("%d %d\n" ,r.first , r.second);
		}
		else {
			sc(x1) ;sc(y1 );sc(val);
			x1 -- , y1--;
			update_x(1, 0, n-1 ,x1 , y1,val);
		}
		
	}
	
	return 0;
}

Second Try : Sqrt- Decompostion.

1. We can divide the whole square / Rectangle in some smaller block which dimension is sqrt(n) x sqrt(n)
2. We store The minimum & maximum of this block in a 2D array ..
3. For updating a point We need just to update the block , where it belongs,
4. For query , We need to traverse thorough lot of case …

Please See the implementation And try to understand how the whole interval is covered.


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

/*------- Constants---- */
#define LMT				600
#define ll				long long
#define ull				unsigned long long
#define mod				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

int block ;
int iA[LMT][LMT];
int partMax[35][35];
int partMin[35][35];
int val;

int main()
{
	
	int n , m ;
	sc(n ); sc(m );
	
	block = sqrt(n) + 1 ;
	FOR(i, block + 5 ){
		FOR(j , block + 5 ){
			partMax[i][j] = -1;
			partMin[i][j] = inf;
		}
	}
	FOR(i, n) {
		int x  = i / block;
		FOR(j, m){
			sc(iA[i][j]);
			partMax [x][j/block] = max( partMax[x][j / block] , iA[i][j] );
			partMin [x][j/block] = min( partMin[x][j / block] , iA[i][j] );
		}
	}
	
	int q , x1 , y1 , x2 , y2 ;
	char ch ;
	sc(q);
	int cnt= 0;
	while (q -- ) {
		do {
			ch = gc();
		} while (ch =='\n'||ch =='\0');
		
		if(ch == 'q') {
			++cnt;
			
			if(cnt == 12 ) {
				
				//cout<<""<<endl;
			}
			
			sc(x1) ;sc(y1) ;sc(x2) ; sc(y2);
			x1 -- , y1 -- , x2 -- , y2 --;
			
			int iMac = -1 , iMin = inf ;
			while(x1 <= x2 && x1 % block != 0 ){
				
				for(int j = y1 ; j <= y2 ; j ++ ) {
					iMac = max(iMac , iA[x1][j]);
					iMin = min(iMin , iA[x1][j]);
				}
				x1 ++;
			}
			
			
			while (x1 + block - 1 <= x2 ) {
				
				int y = y1;
				
				while (y  <= y2 && y % block != 0 ) {
					
					for(int i = x1; i < x1 + block ; i ++ ) {
						iMac = max(iMac , iA[i][y]);
						iMin = min(iMin , iA[i][y]);
					}
					y ++;
				}
				while (y + block -1 <= y2 ) {
					iMac = max(iMac , partMax[x1/block][y /block]);
					iMin = min(iMin , partMin[x1/block][y/block]);
					y += block;
				}
				while( y <= y2 ) {
					for(int i = x1; i < x1 + block ; i ++ ) {
						iMac = max(iMac , iA[i][y]);
						iMin = min(iMin , iA[i][y]);
					}
					y ++;
				}
				
				x1 = x1 + block;
			}
			
			for(int i = x1 ; i <= x2; i ++ ){
				for (int j = y1 ; j <= y2 ; j ++ ) {
					iMac = max(iMac , iA[i][j]);
					iMin = min(iMin , iA[i][j]);
				}
			}
			
			printf("%d %d\n",iMac ,  iMin);
			
			
		}
		else {
			
			
			sc(x1) ; sc(y1 ); sc(val);
			x1 -- ;
			y1 -- ;
			iA[x1][y1] = val;
			
			int i = (x1 / block ) * block;
			int j = (y1 / block ) * block;
			
			partMax[i/block][j /block] = 0;
			partMin[i/block][j/block] = inf;
			for(int L = i ; L < i+ block ; L ++ ) {
				int x = L / block;
				for (int R = j ; R < j + block ; R ++ ) {
					partMax[x][R / block] = max ( partMax[x][R /block ] , iA[L][R]);
					partMin[x][R / block] = min ( partMin[x][R /block ] , iA[L][R]);
				}
			}
		}
	}
	
	return 0;
}

Third Approach :
Maintain 1D segment tree for Each Row.
This one is the easiest one. And also get AC in given time limit..
1. For each row, Maintain a segment tree to so that you can find minimum and maximum value in a given interval.
2. For query operation, iterate through the row , and find the minimum and Maximum Value in the given (y1,y2) interval

See the implementation:



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

/*------- Constants---- */
#define LMT				605
#define ll				long long
#define ull				unsigned long long
#define mod				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

ii seg[LMT][4*LMT];
int row;
int val;

int iA[LMT][LMT];

void build(int n,int b,int e)
{
	if( b == e) {
		seg[row][n] = ii(iA[row][b] , iA[row][b]);
		return;
	}
	
	int mid = (b+e)/2;
	build(lc, b, mid);
	build(rc, mid +1 , e);
	
	seg[row][n].first =  max( seg[row][lc].first , seg[row][rc].first );
	seg[row][n].second = min (seg[row][lc].second , seg[row][rc].second);
	
	
}

void updt(int n,int b,int e,int pos)
{
	if( b == e && b == pos ) {
		seg[row][n].first = val;
		seg[row][n].second = val;
		return;
	}
	
	int mid = (b+e)/2;
	
	if( pos <= mid ) updt(lc , b , mid , pos);
	else updt(rc, mid + 1, e, pos);
	
	seg[row][n].first =  max( seg[row][lc].first , seg[row][rc].first );
	seg[row][n].second = min (seg[row][lc].second , seg[row][rc].second);
	
}

ii query(int n,int b,int e ,int i , int j )
{
	if( b > j || e < i) return ii(-1,inf);
	if( b >= i && e <= j ) {
		return seg[row][n];
	}
	int mid = (b+e) / 2;
	ii r1 = query(lc , b , mid, i, j);
	ii r2 = query(rc , mid + 1, e, i , j);
	
	return ii(max(r1.first , r2.first) , min(r1.second , r2.second));
}


int main()
{
	
	
	int n , m ,q ;
	sc(n) ;sc(m);
	FOR(i, n){
		row = i;
		FOR(j, m) {
			sc(iA[i][j]);
		}
		build(1, 0 , m -1);
	}
	
	sc(q);
	char ch;
	int x1, x2 , y1 , y2;
	
	while (q -- ) {
		do {
			ch =gc();
		} while (ch == '\n' || ch =='\0');
		
		if(ch =='q'){
			sc(x1) ;sc(y1) ;sc(x2); sc(y2);
			x1--,y1--,x2--,y2--;
			ii r = ii(-1,inf);
			for(int i = x1; i <= x2; i ++ ) {
				row = i ;
				ii r1 = query(1, 0, m-1, y1 , y2);
				r.first = max(r.first , r1.first);
				r.second = min(r.second , r1.second);
			}
			
			printf("%d %d\n" , r.first , r.second);
		}
		if( ch =='c'){
			sc(x1);sc(y1) ;sc(val);
			x1 -- ,y1--;
			row = x1;
			updt(1, 0, n-1, y1);
		}
	}
	return 0;
}

I hope there may be other methods to solve this problem . Explore them..

Remark :
2D segment Tree is the best solution
Sqrt Decomposition
Row Based 1D segment Tree

LightOj 1097 – Lucky Number

Approach : Binary Indexed Tree , Segment Tree

Ok ,The first thing to say, Simulation on the array will not work here in the give time limit. We need to use above mentioned data structure.. If you don’t know them ,Then please search on google, know them & come back for solution,,

Ok , I can assume that ,you all know BIT and Segment Tree.

First Solution : BIT


1. As we need to find the nth element in the list of-course efficiently , erase it from the list ..
2. Ok, we don't need manually delete the element for BIT , just make the frequency of that element to zero.
3. So , we need to find the least (why ? )element that has commulatitive frequency = n ; This can be done using binary search
4. Efficient Binary search for BIT can be found in topcoder tutorial. Or simply binary search will also do the work
5. update its value to nullify it

Here is the code :

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

/*------- Constants---- */
#define LMT				100
#define ll				long long
#define ull				unsigned long long
#define mod				1000000007
#define MEMSET_INF		63
#define MEM_VAL			1061109567
#define FOR(i,n)			for( int i=0 ; i < n ; i++ )
#define mp(i,j)			make_pair(i,j)
#define lop(i,a,b)		for( int i = (a) ; i < (b) ; i++)
#define pb(a)			push_back((a))
#define gc				getchar_unlocked
#define PI				acos(-1.0)
#define inf				1<<30
#define lc				((n)<<1)
#define rc				((n)<<1 |1)
#define msg(x)			cout<<x<<endl;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

const int MAC = 2097152;
const int IM = 1429500;
int iBit[MAC + 5 ];

void updt(int n,int val )
{
	// update the n item adding val to it
	while( n <= MAC) {
		iBit[n] +=val;
		n += (n&-n);
	}
}

int bs(int val )
{
	int idx = 0 , d = MAC , tidx;
	val --;
	while (d >0 &&  idx <= MAC ) {
		tidx = idx + d;
		if(tidx <= MAC &&  iBit[tidx] <= val) {
			idx = tidx;
			val -= iBit[tidx];
		}
		d >>= 1;
	}
	return idx + 1;
}

int query (int n)
{
	// Returns Comulative Sum [1.....n]
	
	int sum = 0;
	while (n > 0) {
		sum += iBit[n];
		n -= (n&-n);
		
	}
	return sum;
}

int ans[100005];
int main()
{
	
	int tc , n ,cs = 0 ;
	
	// updating every odd with 1 , even are already deleted
	for(int i = 1;i <= MAC ; i += 2  ) updt(i , 1);
	
	ans[1] = 1;
	int cnt = 2;
	int prv = 1;
	
	for( int i = 3; i <= IM ; i += 2 ){
		
		int k1 = query(i);	// this gives sum [1...i]
		int k = k1  - prv ;	// prv stores query(i-1) , We store it to avoid double counting
		
		// if k ==1 , then i th element is not deleted from the list
		
		if(k ) {
			ans[cnt ++] = i ; // add in the answer array
			int p = (IM / i ) * i  ; // Starting from Rightmost pos , this update willnot affect the [1 ..... p-1] update
			while(p >= i ) {
				int pk = bs(p);	// Find the number which is the p th element in the list
				updt(pk , -1);	// Update it -1 , as we added 1 to each of the, nullify is done with -1 update
				p-= i ;
			}
			prv = k1;
			
		}
	}
	sc(tc);
	while (tc -- ) {
		sc(n);
		printf("Case %d: %d\n", ++cs , ans[n]);
	}
	
	return 0;
}

This goes BIT ..

Second Solution : Segment tree
1. Here every segment stores how many number that is not deleted on that segment,
2. If we want to find the n th element on the list , We start from the top ,
3. if its left child has more than or equal number than go left
4. Else go right ,Adjust the value of n , Because we already left the left subtree, all the number will be subtracted then n will be n - seg[left]
5. Update method is done in the same manner, We update the nth element and make it 0. (This is similar to delete ).

Continue reading

LightOj – 1276 – Very Lucky Numbers

Approach : Complete Search , Branch & Bound
1 . First generate the lucky number
2 . Sort The lucky Number
3 . Then again Run recursive function with careful pruning , store all the very lucky into a vector to set
4. Binary search on the sorted list ( Can use upper_bound, lower_bound also)

MAX = 10^12
So use long long in all calculation
To avoid overflow always check if it is <= MAX ||

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

/*------- Constants---- */
#define MX                      100005
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */

template<class T > void sc(T &x){
	register T c = gc();
	register int sign = (c=='-' ?-1:1);
	x = 0;
	for(;(c<48 || c>57);c = gc());
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	x = x*sign;
}
template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

const ll MAC = 1000000010001;
vector<ll> lucky;

void cal(ll sum)
{
	if(sum > 0 && sum < MAC){
		lucky.push_back(sum);
	}
	if(sum > MAC) return;
	cal(sum * 10 + 4);
	cal(sum * 10 + 7);

}

vector<ll>vrLucky;
set<ll> Sk;
void backTr(ll ix, ll sum)
{
	if(sum > MAC ) return;

	if(sum < MAC && sum > 1) {
		Sk.insert(sum);
	}

	if(ix >= lucky.size() ) {
		if(sum < MAC && sum > 1 ) {
			Sk.insert(sum);
		}
		return;
	}

	if( sum <= MAC / lucky[ix] ) backTr(ix , sum * lucky[ix]); //Use the number more than one time 
	if( sum <= MAC / lucky[ix] ) backTr(ix + 1, sum); // Don’t use this number
	if( sum <= MAC / lucky[ix] ) backTr(ix + 1, sum * lucky[ix]); // Use the once, go to the next number. As the numbers are sorted the following conditions always holds

	return;

}

ll bs(ll val)
{
	int L = 0, H = (int)vrLucky.size() , mid , ans = L - 1 ;
	while (L <= H ) {
		mid = (L + H ) >> 1;
		if(vrLucky[mid] <= val) {
			ans = mid;
			L = mid + 1;
		}
		else H = mid - 1;
	}
	return ans ;
}

int main()
{

	cal(0);
	sort(lucky.begin(), lucky.end());
	backTr(0 , 1);

	set<ll> ::iterator it= Sk.begin();
	while(it != Sk.end() ){
		vrLucky.push_back(*it);
		it++;
	}
	//Sk.clear();
	ll tc , cs = 0 , a , b ;
	sc(tc);
	while (tc -- ) {
		sc(a) ;sc(b);

		printf("Case %lld: %ld\n", ++cs , upper_bound(vrLucky.begin() , vrLucky.end() , b) - lower_bound(vrLucky.begin(), vrLucky.end(), a));

	}
	return 0;
}

This code will give use T = 1.6 ~ 1.9 sec

But We can improve using following manner..

1. Using normal array , and increase its counter by 1 for each insertion

Rest of the explanation in the code :

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

/*------- Constants---- */
#define MX                      100005
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */

template<class T > void sc(T &x){
	register T c = gc();
	register int sign = (c=='-' ?-1:1);
	x = 0;
	for(;(c<48 || c>57);c = gc());
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	x = x*sign;
}
template <class T> inline T bigmod(T p,T e,T M){
	ll ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

const ll MAC = 1000000000008;
const int MAXN = 500000;
int cnt = 0 ;
int pk = 0;
ll lucky[MAXN];

void cal(ll sum)
{
	// generating The lucky Number
	if(sum > 0 && sum < MAC){
		lucky[cnt++] = sum;
	}
	if(sum > MAC  ) return;
	cal(sum * 10 + 4);
	cal(sum * 10 + 7);

}

void backTr(ll sum , int st ) // generating Very lucky Number
{
	if(sum > MAC || sum <=0 ) return;
	if(sum > 1 ) lucky[pk++] = sum; // insertion

	for(int i = st ; i < cnt ; i ++ ) {
		// For each lucky number we do the following 

		ll k = lucky[i] * sum ;

		if(k > MAC || k <=0 ) break;

		// We multiply it with itself and 
		//Rest of the lucky number on its Right side  && call the Recursion with
                // multiplied value

		backTr(k , i);
	}
}

int main()
{

	cal(0);
	sort(lucky, lucky + cnt);
	pk = cnt;
	backTr(1 , 0);
	sort(lucky, lucky + pk);
	ll sz = unique(lucky , lucky + pk ) - lucky;

	int tc , cs = 0;
	ll a, b ;
	sc(tc);
	while (tc -- ) {
		sc(a) ;sc(b);
		printf("Case %d: %ld\n" ,++cs,  upper_bound(lucky , lucky+sz, b) - lower_bound(lucky, lucky + sz , a));
	}

	return 0;
}

LightOj 1127 – Funny Knapsack

Approach : Meet-in-the-Middle, Combination Generation

n <=30 , First Approach is typical DP with map

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

/*------- Constants---- */
#define LMT                     100
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1LL)
#define rc                      ((n)<<1LL |1)
/* -------Global Variables ------ */
ll euclid_x,euclid_y,d;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

/*************************** END OF TEMPLATE ****************************/

int  n , w;
int iA[35];
map<int , int > dp[35];

int backTr(int nth,int sum )
{
	if(sum > w ) return 0;
	if(nth >= n ) {
		if(sum <= w ) return 1;
	}
	if(dp[nth].count(sum) ) return dp[nth][sum];
	
	return dp[nth][sum] = backTr(nth + 1, sum ) + backTr( nth + 1, sum +iA[nth] );
	
}int main()
{
	
	int tc , cs = 0 ;
	sc(tc);
	while (tc -- ) {
		sc(n); sc(w);
		FOR(i , n) sc(iA[i]);
		printf("Case %d: %d\n", ++cs , backTr(0 , 0));
		FOR(i, 35) dp[i].clear();
	}
	return 0;
}

But Above Approach will give MLE (MEMORY LIMIT EXCCEDED)

Approach 2 :

We split the array in two equal division and generate every combination on that two set. The number generated in two set is separately kept in 2 vectors
- > Sort any of the array. For each element in unsorted array , We binary search the largest index so that their sum is <= w ; - > Add this value to the answer.

Here is the full code :


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

/*------- Constants---- */
#define LMT                     100
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1LL)
#define rc                      ((n)<<1LL |1)
/* -------Global Variables ------ */
ll euclid_x,euclid_y,d;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

/*************************** END OF TEMPLATE ****************************/

int  n , w;
int iA[35];
int lim  ;
vector<ll> L , H ;
void cal(int i,ll sum ,bool fl )
{
	if(sum > w) return ;
	if( i > lim ){
		if(sum <= w) {
			if(fl )L.push_back(sum);
			else H.push_back(sum);
		}
		return;
	}
	
	cal(i + 1, sum ,fl );
	cal(i + 1, sum + iA[i],fl );
}


int bs(ll val)
{
	int low = 0 , high =(int ) H.size() - 1 , mid , ans =low -1;
	while (low <= high ) {
		mid = (low + high ) >>1;
		if(H[mid] <= val) {
			ans = mid ;
			low = mid + 1;
		}
		else high = mid - 1;
	}
	return ans ;
}

int main()
{
	
	int tc , cs = 0 ;
	sc(tc);
	while (tc -- ) {
		sc(n); sc(w);
		FOR(i , n) sc(iA[i]);
		lim = n / 2;
		cal(0 , 0,true );
		lim = n - 1 ;
		cal(n / 2 + 1 , 0 ,false );
		
		sort(L.begin(), L.end());
		sort(H.begin(), H.end());
		int ans = 0;
		for(int i = 0; i < L.size() ; i ++ ) {
			int k =  bs ( w - L[i]);
			ans += k +1;
		}
		
		printf("Case %d: %d\n",++cs , ans );
		L.clear();
		H.clear();
	}
	return 0;
}


Similar Problem : Lightoj 1235 – Coin Change (IV)

LightOj 1307 – Counting Triangles

Approach : Binary Search , Sorting

To maintain triangle Property, length of the triangle should
a + b > c ;

So we sort the array of lengths. Then We pick two sticks(a,b) , And find the index(i) which length is less than a + b ,So this all length within this index satisfy triangle property.

Here is the code

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

/*------- Constants---- */
#define LMT                     2005
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1LL)
#define rc                      ((n)<<1LL |1)
/* -------Global Variables ------ */
ll euclid_x,euclid_y,d;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

/*************************** END OF TEMPLATE ****************************/


int iA[LMT];


int bs(int L,int H,int val)
{
	int mid , ans = L - 1;
	while (L <= H ) {
		mid = (L + H ) >> 1;
		if(iA[mid] < val) {
			ans = mid ;
			L = mid + 1;
		}
		else H = mid - 1;
	}
	return ans;
}
int main()
{
	
	int tc , cs =0 , n , ans ;
	sc(tc);
	while(tc -- ){
		sc(n);
		FOR(i , n) sc(iA[i]);
		sort(iA, iA+n);
		
		ans = 0 ;
		register int i , j ;
		for( i = 0 ;i < n ; i ++ ) {
			for( j = i + 1 ; j < n ; j ++ ) {
				ans += bs(j+1 , n - 1, iA[i] + iA[j]) - j ;
			}
		}
		
		printf("Case %d: %d\n", ++cs, ans );
	}
	return 0;
}


Ok The complexity is O(n^2 log n )

Another good solution :
We iterate through the array. Making iA[i] = c ,
Then each value of R from i-1 ,to 0
find smallest L , such that iA[L] + iA[R] > c;
Add R- L to answer..


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

/*------- Constants---- */
#define LMT                     2005
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1LL)
#define rc                      ((n)<<1LL |1)
/* -------Global Variables ------ */
ll euclid_x,euclid_y,d;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

/*************************** END OF TEMPLATE ****************************/


int iA[LMT];

int main() {
	
	int tc , cs = 0 , n , ans  ;
	sc(tc) ;
	while (tc -- ) {
		sc(n);
		FOR(i, n) sc(iA[i]);
		sort(iA , iA + n);
		int i , L , R ;
		ans = 0 ;
		for ( i = 0 ; i < n ; i ++ ) {
			L = 0;
			for (R = i - 1 ; R > 0; R -- ) {
				while ( L < R && iA[L] + iA[R] <= iA[i]) L ++;
				if(L >= R ) break;
				ans += R - L ;
				
			}
		}
		
		printf("Case %d: %d\n" , ++cs , ans );
	}
	return 0;
}

This solution is O(n^2)

LightOj – 1048 – Conquering Keokradong

Approach : Binary Search

1. To find the minimum walk ->
Ok , if n is the minimum walk for the question , then using n + 1 , we can cover the whole distance with k camp breaks. And this is true for every number > n .

Now , n-1 , This can be answer. If we can cover the whole distance by n -1 walk, Then n-1 ,would be the answer.

This two observation is the essence of binary search.

So , We select a mid , Simulate with this selected value, And see if it is possible to cover the distance with k camp breaks. If it is possible , Decrease high value , otherwise increase low value..

For explanation See the code


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

/*------- Constants---- */
#define LMT                     1005
#define ll                      long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define FOR(i,n)                for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1LL)
#define rc                      ((n)<<1LL |1)
/* -------Global Variables ------ */
ll euclid_x,euclid_y,d;

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
inline void sc(int &x)
{
	register int c = gc();
	x = 0;
	int neg = 0;
	for(;((c<48 | c>57) && c != '-');c = gc());
	if(c=='-') {neg=1;c=gc();}
	for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
	if(neg) x=-x;
}

/*************************** END OF TEMPLATE ****************************/

int iAr[LMT];
int n , k ;

int can(int dis)
{
	int sum = 0 ;
	int cnt = 0 ;
	for (int i = 0 ; i <= n ; i ++ ) {
		if(iAr[i] > dis) return inf;
		if(iAr[i] + sum  == dis ) {
			cnt ++;
			sum = 0;
		}
		else if(iAr[i] + sum > dis ) {
			cnt ++;
			sum = iAr[i];
		}
		else sum = iAr[i] + sum ;
		
	}
	if(sum ) cnt ++;
	return cnt;
}


void Trv (int dis)
{
	int sum = 0 ;
	int cnt = 0;
	for(int i = 0; i <= n ; i ++ ) {
		if( sum + iAr[i] > dis ) {
			printf("%d\n" , sum);
			cnt ++;
			sum = iAr[i];
		}
		else if( sum + iAr[i] == dis  ) {
			printf("%d\n" , sum + iAr[i]);
			cnt ++;
			sum = 0 ;
		}
		
		else if( n - i == k - cnt ) {
			printf("%d\n" , sum + iAr[i]);
			cnt ++;
			sum = 0;
		}
		else sum += iAr[i];
	}
}

int main()
{
	
	int tc , cs = 0  ;
	sc(tc);
	while (tc -- ) {
		sc(n) ; sc(k );
		
		FOR(i , n + 1) {
			sc(iAr[i]);
		}
		
		int L = 0 , H = 100006 , mid , ans;
		while (L <= H ) {
			mid = (L + H) >> 1;
			if(can(mid) <= k+1 ) {
				ans = mid ;
				H = mid - 1;
			}
			else L = mid + 1;
		}
		
		
		printf("Case %d: %d\n" , ++cs, ans );
		
		Trv(ans);
		
	}
	
	return 0;
}


Similar Problem :