Page 1 of 1

11868 - Game of Blocks

Posted: Sun Oct 31, 2010 10:10 pm
by Leonid
Hey guys, this thread is for someone who maybe has at least approached this problem.

It can be deduced to matrix exponentiation problem, which can be solved relatively efficiently in O(N^2.376*log(max(leni))) using Coppersmith-Winograd algorithm and fast exponentiation. But it seems that a more efficient algorithm is required, as Coppersmith-Winograd implies a large constant factor. Do you have any other ideas?

JPvdMerwe suggested approach to divide the range repeatedly by 2. But as discussed it seems to be a bit inefficient.

Re: 11868 - Game of Blocks

Posted: Fri Nov 05, 2010 3:27 pm
by Angeh
i implemented this approach, but i time out :((
could someone help us on this ?
thanks in advance

Re: 11868 - Game of Blocks

Posted: Fri Nov 05, 2010 7:47 pm
by Leonid
Angeh, what optimizations have you tried?

Re: 11868 - Game of Blocks

Posted: Fri Nov 05, 2010 7:55 pm
by Angeh
i didnt use many optimization ... only used Memorization (Using STL map )...
also Calculated the result for i:0...10^6 using incremental method ... it tool 4s To calculate FOR 10^6

but FOR this Test Case
2
750 749
999999999999999

it took minutes to complete ...
so i didnt try much other minor optimizations like reducing number of * or % ...

There should be other method to solve this Test Case ...
100
750 749 748 747 746 745 744 743 742 741 740 739 738 737 736 735 734 733 732 731
730 729 728 727 726 725 724 723 722 721 720 719 718 717 716 715 714 713 712 711
710 709 708 707 706 705 704 703 702 701 700 699 698 697 696 695 694 693 692 691
690 689 688 687 686 685 684 683 682 681 680 679 678 677 676 675 674 673 672 671
670 669 668 667 666 665 664 663 662 661 660 659 658 657 656 655 654 653 652 651
999999999999999

one other possible optimization could be to avoid computing for same block sizes and just calculate distinct sizes ...
but it would not work in worst Case ....

in Rank list There are ACs below 2s ... :( i wonder whats the Right approach !!

Code: Select all

#include<iostream>
#include<algorithm>
#include<map>
#include<ctime>
using namespace std;
#define FOR(i,n) for(int i=0;i<n;++i)
map<long long ,long long> DP;
long long memorize[1000000];
const long long Mode= 100000007;
int in[128],n;
long long Find(long long range){
    //printf("%lld\n",range);
    if(DP.count(range) )return DP[range];
    long long res=0;
    FOR(i,n){
        if(in[i]>range)continue;
        else if(in[i]==range)res+=1;
        else {
            FOR( r,in[i] ){
                long long a= range/2-in[i]+r+1,
                    b= range-(range/2+r)-1;
                //printf("%lld %lld %lld\n",a,b,range );
                if(a<0 || b<0)continue;
                res= ( res+(Find(a)*Find(b)) )%Mode;
            }
        }
    }
    return ( DP[range]=res%Mode );
}
int main(){
    //FOR(i,100)printf("%d ",750-i );
    freopen("in.txt","r",stdin);
    int cas;
    scanf("%d",&cas);
    FOR(ca,cas){
        DP.clear();
        scanf("%d",&n);
        int mini=214778;
        FOR(i,n){
            scanf("%d",&in[i] );
            mini=min(mini,in[i] );
        }
        FOR(i,mini) DP[i]=memorize[i]=0;
        DP[0]=memorize[0]=1;

        long long range;
        scanf("%lld",&range);

        //long long start=clock();
        int Max=min<long long>(1000000,range+1 );
        
        for(int i=mini;i<Max;++i){
            memorize[i]=0;
            FOR(j,n)if(in[j]<=i)memorize[i]+=memorize[ i-in[j] ];
            memorize[i]%=Mode;
            DP[i]=memorize[i];
        }

        //printf("PreTime : %lld\n",clock()-start );
        //start=clock();
        long long res=Find(range);
        //long long end=clock();
        pr//intf("Time : %lld\n",end-start );
        printf("Case %d: %lld\n",ca+1,res);        
        //break;
    }
    return 0;
}

Re: 11868 - Game of Blocks

Posted: Fri Nov 05, 2010 11:04 pm
by Leonid
The solution can be improved by using hashes, by at least a factor of 10. And MOD operation can be done only in the outer loop, that could improve the solution by around a factor of 2. How many seconds does it currently take on the maximum possible test? How many states there are in the map in the worst possible case? Robert Gericz, who wrote the fastest solution under 1 second is expert in number theory and usually writes highly optimized solutions. However, for some reason he used C++ (wondering why?? ).

Re: 11868 - Game of Blocks

Posted: Sun Nov 07, 2010 6:12 am
by tanaeem
My solution is polynomial exponentiation instead of matrix exponentiation. Basic steps are
1. Find a polynomial P(x) of degree 750.
2. Find R(x)=(x^n) mod P(x)
3. Replace x^i by F_i in R(x). The answer is solution.
The polynomial P(x) is related to generating function and I am leaving the detail.
This method can be proved using Cayley–Hamilton theorem.
The problem is inspired by Project Euler problem 258.
http://projecteuler.net/index.php?secti ... ems&id=258

My solution takes more than 13s. I have no idea what Robert Gericz have done.

Re: 11868 - Game of Blocks

Posted: Mon Nov 08, 2010 1:21 am
by Leonid
What is the complexity of your solution? There exists a solution with complexity O( (L^2 + L*C) * log N ) which is described in this thread.