Monday, January 21, 2013

Codechef ARIGEOM

Link : ARIGEOM

Category : Pigeonhole principle


Solution : Consider the first three terms. Some two of them have to be in AP or both in GP, thus giving 6 possible cases. Eg, let a,b,and c be first three terms. If a and b form an AP, then common difference of the AP must be b-a. Now mark all elements falling in this AP as apmarked (remember, all elements must be present in this AP starting from a and ending at some end point within the array). Now for remaining elements, find the common ratio that would mark all remaining elements, and possibly some apmarked elements too. Similarly for other 5 cases too.

Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <climits>
#include <cfloat>
#include <cassert>
using namespace std;
#define readint(n) scanf("%d",&n)
#define readull(n) scanf("%llu",&n)
#define readll(n) scanf("%lld",&n)
#define readf(n) scanf("%f",&n)
#define readlf(n) scanf("%lf",&n)
#define init(mem) memset(mem,0,sizeof(mem))
#define ull unsigned long long int
#define ll long long int
#define setmax(a,b) a=max(a,b)
#define setmin(a,b) a=min(a,b)
inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
struct frac{
ll n,d;
frac(){}
frac(ll n1,ll d1){
n=n1;
d=d1;
ll g=gcd(n,d);
n/=g;
d/=g;
}
};
inline frac getcommonroot(frac a,frac b){
//printf("%lld %lld %lld %lld\n",a.n,a.d,b.n,b.d);
if(a.n*b.d>a.d*b.n) swap(a,b);
if(a.n==1 and a.d==1) return b;
if((b.n*a.d)%(b.d*a.n)!=0) return a;
return getcommonroot(a,frac(b.n*a.d,b.d*a.n));
}
int t,n;
ll arr[10001];
bool apmarked[10001];
bool gpmarked[10001];
bool testAP(int ind1,int ind2){
init(apmarked);
init(gpmarked);
int markcnt=0;
apmarked[ind1]=1;
apmarked[ind2]=1;
markcnt=2;
ll diff=arr[ind2]-arr[ind1];
int ptr=ind2+1;
ll next=arr[ind2]+diff;
while(ptr<n){
if(arr[ptr]==next){
apmarked[ptr]=1;
markcnt++;
next+=diff;
if(next>arr[n-1]) break;
}
ptr++;
}
if(markcnt==n or markcnt==n-1){
int unmarked=0;
for(int i=0;i<n;i++){
if(!apmarked[i]){
unmarked=i;
break;
}
}
for(int i=0;i<n;i++){
if(apmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
if(unmarked==n-1){
printf("%lld %lld\n",arr[unmarked-1],arr[unmarked]);
}
else{
printf("%lld %lld\n",arr[unmarked],arr[unmarked+1]);
}
return true;
}
if(markcnt==n-2){
for(int i=0;i<n;i++){
if(apmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
for(int i=0;i<n;i++){
if(!apmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
return true;
}
int prevunmarked=0;
while(apmarked[prevunmarked]) prevunmarked++;
frac ratio(1,1);
for(int i=prevunmarked+1;i<n;i++){
if(!apmarked[i]){
ratio=getcommonroot(ratio,frac(arr[i],arr[prevunmarked]));
prevunmarked=i;
}
}
ptr=0;
while(apmarked[ptr]) ptr++;
gpmarked[ptr]=true;
markcnt++;
if((arr[ptr]*ratio.n)%ratio.d==0){
next=(arr[ptr]*ratio.n)/ratio.d;
ptr++;
while(ptr<n){
if(next>arr[n-1]) break;
if(arr[ptr]==next){
gpmarked[ptr]=true;
if(!apmarked[ptr]) markcnt++;
if((arr[ptr]*ratio.n)%ratio.d!=0) break;
next=(arr[ptr]*ratio.n)/ratio.d;
}
ptr++;
}
if(markcnt==n){
for(int i=0;i<n;i++){
if(apmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
for(int i=0;i<n;i++){
if(gpmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
return true;;
}
}
return false;
}
bool testGP(int ind1,int ind2){
init(apmarked);
init(gpmarked);
int markcnt=0;
gpmarked[ind1]=1;
gpmarked[ind2]=1;
markcnt=2;
bool justcheckap=false;
frac ratio(arr[ind2],arr[ind1]);
if(((arr[ind2]*ratio.n)%ratio.d)!=0){
justcheckap=true;
}
ll ptr=ind2+1,next=(arr[ind2]*ratio.n)/ratio.d;
if(!justcheckap){
while(ptr<n){
if(next>arr[n-1]) break;
if(arr[ptr]==next){
gpmarked[ptr]=true;
if(((next*ratio.n)%ratio.d)!=0) break;
next=(next*ratio.n)/ratio.d;
markcnt++;
}
ptr++;
}
}
if(markcnt==n or markcnt==n-1){
int unmarked=0;
for(int i=0;i<n;i++){
if(!gpmarked[i]){
unmarked=i;
break;
}
}
if(unmarked==n-1){
printf("%lld %lld\n",arr[unmarked-1],arr[unmarked]);
}
else{
printf("%lld %lld\n",arr[unmarked],arr[unmarked+1]);
}
for(int i=0;i<n;i++){
if(gpmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
return true;
}
if(markcnt==n-2){
// printing
for(int i=0;i<n;i++){
if(!gpmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
for(int i=0;i<n;i++){
if(gpmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
return true;
}
int prevunmarked=0;
while(gpmarked[prevunmarked]) prevunmarked++;
ll diff=0;
for(int i=prevunmarked+1;i<n;i++){
if(!gpmarked[i]){
diff=gcd(diff,arr[i]-arr[prevunmarked]);
prevunmarked=i;
}
}
ptr=0;
while(gpmarked[ptr]) ptr++;
apmarked[ptr]=1; // AP starter
next=arr[ptr]+diff;
while(ptr<n){
if(next>arr[n-1]) break;
if(arr[ptr]==next){
apmarked[ptr]=1;
next+=diff;
}
ptr++;
}
markcnt=0;
for(int i=0;i<n;i++){
if(gpmarked[i] or apmarked[i]) markcnt++;
}
if(markcnt==n){
for(int i=0;i<n;i++){
if(apmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
for(int i=0;i<n;i++){
if(gpmarked[i]){
printf("%lld ",arr[i]);
}
}
printf("\n");
return true;
}
return false;
}
int main(){
readint(t);
while(t--){
readint(n);
for(int i=0;i<n;i++){
readll(arr[i]);
}
if(n==2){
printf("%lld %lld\n",arr[0],arr[1]);
printf("%lld %lld\n",arr[0],arr[1]);
continue;
}
if(testAP(0,1)) continue;
if(testGP(0,1)) continue;
if(testAP(0,2)) continue;
if(testGP(0,2)) continue;
if(testAP(1,2)) continue;
if(testGP(1,2)) continue;
assert(false);
}
return 0;
}
view raw ARIGEOM.cpp hosted with ❤ by GitHub

Friday, January 11, 2013

SPOJ DCEPC206

Link : DCEPC206

Category : Segment Tree


Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <ctime>
#include <utility>
#include <climits>
#include <cfloat>
#include <cassert>
using namespace std;
#define readint(n) scanf("%d",&n);
#define readll(n) scanf("%lld",&n);
#define readchar(n) scanf("%c",&n);
#define readf(n) scanf("%f",&n);
#define readd(n) scanf("%lf",&n);
#define readstr(s) scanf("%s",&s);
#define init(mem) memset(mem,0,sizeof(mem));
int pabs(int n){return (n>0?n:-n);}
int hcf(int a,int b){if(b==0){return a;} else{return hcf(b,a%b);}}
long long int mem[4000004];
int n;
void update(int ind,int l,int u,int v){
if(v<l or v>u)return;
if(l==u){
mem[ind]+=l;
return;
}
int mid=(l+u)/2;
update(2*ind,l,mid,v);
update(2*ind+1,mid+1,u,v);
mem[ind]=(mem[ind*2]+mem[2*ind+1]);
}
long long int query(int ind,int l,int u,int x,int y){
if(u<x or l>y){
return 0;
}
if(x<=l and u<=y){
return mem[ind];
}
int mid=(l+u)/2;
return query(2*ind,l,mid,x,y)+query(2*ind+1,mid+1,u,x,y);
}
int main(){
int t,v;
readint(t);
while(t--){
init(mem);
readint(n);
long long int sum=0;
for(int i=1;i<=n;i++){
readint(v);
sum+=query(1,1,1000001,1,v-1);
update(1,1,1000001,v);
}
printf("%lld\n",sum);
}
return 0;
}
view raw DCEPC206.cpp hosted with ❤ by GitHub

Tuesday, January 8, 2013

SPOJ SKYLINE

Link : SKYLINE

Category :Maths


Solution : Recurrence works out to be Catalan number.


Code:
var cat:array[1..1001] of int64;
var n:longint;
const md:int64=1000000;
procedure prep();
var i,j:longint;
var tmp:int64;
begin
cat[1]:=1;
for i:=2 to 1001 do begin
cat[i]:=0;
for j:=1 to i-1 do begin
tmp:=(cat[j]*cat[i-j]) mod md;
cat[i]:=cat[i]+tmp;
end;
cat[i]:=cat[i] mod md;
end;
end;
begin
prep();
while true do begin
readln(n);
if n=0 then break;
writeln(cat[n+1]);
end;
end.
view raw skyline.pas hosted with ❤ by GitHub

Monday, January 7, 2013

SGU 355 : Numbers Painting

Link : sgu355

Category : Simple number theory
Solution :  For every M in 2 to N, let prime factorization of M be M=product(piei). Then M will be colored by color number sum(ei). Eg, 12=22x31, then color 12 by color number (2+1)=3. Additionally, number 1 will require a totally different color, since it divides all other numbers.

Code:
var n,n0,n1,i,maxfacts,facts:longint;
colors:array[1..10000] of longint;
begin
readln(n0);
if n0=1 then
begin
writeln(1);
writeln(1);
exit;
end;
maxfacts:=1;
for n1:=2 to n0 do
begin
n:=n1;
facts:=0;
i:=2;
while i*i<=n do
begin
if n mod i=0 then
begin
while n mod i=0 do
begin
n:=trunc(n/i);
inc(facts);
end;
end;
inc(i);
end;
if n>1 then inc(facts);
if facts>maxfacts then maxfacts:=facts;
colors[n1]:=1+facts;
end;
writeln(maxfacts+1);
write(1,' ');
for i:=2 to n0 do
write(colors[i],' ');
end.
view raw sgu355.pas hosted with ❤ by GitHub