SPOJ: SUMSUM – Enjoy Sum with Operations

Problem Link : http://www.spoj.com/problems/SUMSUM/

Solution Idea:

    This one is a interesting problem. The main idea behind the problem is combinatorics. At first we need to count the number of 1 bit and number of 0 bit in the i_th position of a given number. Then we need to do some combinatorial calculation.

    Now think about an array of 4 number A=[1,0,1,0]. If we perform OR operation in the range 1 to 4 what will we get? We get 5 as answer. If we form pair from this number and perform OR operation between then then we will get the answer. Now as here is 4 element so we can perform pair in 4*(4-1)/2 = 6 ways. Now comes the tricky part. For OR operation how many pair will contribute nothing ?? Here is 2 zero and we can form 1 pair from this two element who will not contribute anything. So for i_th bit position the contribution for OR operation is number_of_active_pair*(2^i).

    For AND operation we need to consider the number of pair can be form by 1 bit and for XOR the number of pair will be number_of_one_bit*number_of_zero_bit.

    We can consider a number as an array of 30 element whose value is either 0 or 1 and perform above operation.



#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pii              pair <int,int>
#define pll              pair <long long,long long>
#define sc               scanf
#define pf               printf
#define Pi               2*acos(0.0)
#define ms(a,b)          memset(a, b, sizeof(a))
#define pb(a)            push_back(a)
#define MP               make_pair
#define db               double
#define ll               long long
#define EPS              10E-10
#define ff               first
#define ss               second
#define sqr(x)           (x)*(x)
#define D(x)             cerr<<#x " = "<<(x)<<endl
#define VI               vector <int>
#define DBG              pf("Hi\n")
#define MOD              1000000007
#define CIN              ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define SZ(a)            (int)a.size()
#define sf(a)            scanf("%d",&a)
#define sfl(a)           scanf("%lld",&a)
#define sff(a,b)         scanf("%d %d",&a,&b)
#define sffl(a,b)        scanf("%lld %lld",&a,&b)
#define sfff(a,b,c)      scanf("%d %d %d",&a,&b,&c)
#define sfffl(a,b,c)     scanf("%lld %lld %lld",&a,&b,&c)
#define stlloop(v)       for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define loop(i,n)        for(int i=0;i<n;i++)
#define loop1(i,n)       for(int i=1;i<=n;i++)
#define REP(i,a,b)       for(int i=a;i<b;i++)
#define RREP(i,a,b)      for(int i=a;i>=b;i--)
#define TEST_CASE(t)     for(int z=1;z<=t;z++)
#define PRINT_CASE       printf("Case %d: ",z)
#define LINE_PRINT_CASE  printf("Case %d:\n",z)
#define CASE_PRINT       cout<<"Case "<<z<<": "
#define all(a)           a.begin(),a.end()
#define intlim           2147483648
#define infinity         (1<<28)
#define ull              unsigned long long
#define gcd(a, b)        __gcd(a, b)
#define lcm(a, b)        ((a)*((b)/gcd(a,b)))

using namespace std;

//using namespace __gnu_pbds;
//typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;


/*----------------------Graph Moves----------------*/
//const int fx[]={+1,-1,+0,+0};
//const int fy[]={+0,+0,+1,-1};
//const int fx[]={+0,+0,+1,-1,-1,+1,-1,+1};   // Kings Move
//const int fy[]={-1,+1,+0,+0,+1,+1,-1,-1};  // Kings Move
//const int fx[]={-2, -2, -1, -1,  1,  1,  2,  2};  // Knights Move
//const int fy[]={-1,  1, -2,  2, -2,  2, -1,  1}; // Knights Move
/*------------------------------------------------*/

/*-----------------------Bitmask------------------*/
//int Set(int N,int pos){return N=N | (1<<pos);}
//int reset(int N,int pos){return N= N & ~(1<<pos);}
bool check(int N,int pos){return (bool)(N & (1<<pos));}
/*------------------------------------------------*/

#define mx 100005

int tree[28][mx];

void update(int id, int idx, int val)
{
    for(;idx<mx && idx;idx+=idx&-idx)
        tree[id][idx]+=val;
}

ll query(int id, int idx)
{
    ll ret=0;
    for(;idx;idx-=idx&-idx)
        ret+=tree[id][idx];
    return ret;
}

int ara[mx];

int main()
{
//    freopen("in.txt","r",stdin);
//	  freopen("out.txt","w",stdout);

    int n,q;
    sff(n,q);
    for(int i=1;i<=n;i++) sf(ara[i]);

    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<28;j++)
        {
            if(check(ara[i],j))
                update(j,i,1);
        }
    }

    while(q--)
    {
        int a,b,c;
        sf(a);
        if(a==1)
        {
            sff(b,c);
            for(int i=0;i<28;i++)
            {
                if(check(ara[c],i))
                    update(i,c,-1);
            }
            ara[c]=b;
            for(int i=0;i<28;i++)
            {
                if(check(ara[c],i))
                    update(i,c,1);
            }
        }
        else
        {
            char ss[10];
            scanf(" %s",&ss);
            string str=string(ss);
            sff(b,c);
            ll temp[30];
            for(int i=0;i<28;i++)
            {
                temp[i]=query(i,c);
            }
            for(int i=0;i<28;i++)
            {
                temp[i]-=query(i,b-1);
            }

            ll ans=0;

            for(int i=0;i<28;i++)
            {
                ll one=temp[i];
                ll zero=(c-b+1)-one;
                ll pairs=0;
                if(str=="OR")
                {
                    ll total=one+zero;
                    pairs=(total*(total-1))/2;
                    pairs-=(zero*(zero-1))/2;
                }
                else if(str=="AND")
                {
                    pairs=(one*(one-1))/2;
                }
                else if(str=="XOR")
                {
                    pairs=one*zero;
                }
                ans+=(1LL<<i)*pairs;
            }

            printf("%lld\n",ans);
        }
    }


    return 0;
}

Advertisements

SPOJ: SQFREE – Square-free integers

Problem Link : http://www.spoj.com/problems/SQFREE/

Solution Idea:

Basic operation of mobius function. Generate mobius function. Then think about every number whose mobius function value is not zero. If we squre them then something we can get.


#include <bits/stdc++.h>

#define ms(a,b)          memset(a, b, sizeof(a))
#define pb(a)            push_back(a)

#define ss               second
#define sqr(x)           (x)*(x)

#define SZ(a)            (int)a.size()
#define sf(a)            scanf("%d",&a)
#define sfl(a)           scanf("%lld",&a)


#define TEST_CASE(t)     for(int z=1;z<=t;z++)
#define ll long long

using namespace std;

#define mx 10000007

int ara[mx];
vector<ll>num,mobius,prime;
bitset<mx/2>vis;

void sieve()
{
    int x=mx/2,y=sqrt(mx)/2;

    for(int i=1;i<y;i++)
    {
        for(int j=i*(i+1)*2;j<x;j+=(2*i+1))
            vis[j]=1;
    }

    prime.pb(2);
    for(int i=3;i<mx;i+=2)
        if(vis[i/2]==0)
            prime.pb(i);

}

void precal()
{
    fill(ara,ara+mx,1);
    for(int i=0;prime[i]*prime[i]<mx;i++)
    {
        ll x=prime[i]*prime[i];
        for(int j=x;j<mx;j+=x)
            ara[j]=0;
    }

    for(int i=0;i<SZ(prime);i++)
    {
        int x=prime[i];
        for(int j=x;j<mx;j+=x)
            ara[j]*=-1;
    }

    for(int i=2;i<mx;i++)
    {
        if(ara[i]==0) continue;
        num.pb(i);
        mobius.pb(ara[i]);
    }

}

int main()
{

//    freopen("in.txt","r",stdin);
//	  freopen("out.txt","w",stdout);
    sieve();
    precal();

    int t;
    sf(t);
    TEST_CASE(t)
    {
        ll n;
        sfl(n);

        ll ans=n;

        for(int i=0;i<SZ(num);i++)
        {
            ll x=num[i];
            ll zz=sqr(x);
            if(zz>n) break;
            int y=mobius[i];
            ans+=mobius[i]*(n/zz);
        }

        printf("%lld\n",ans);

    }

    return 0;
}

nCr%m when m is not prime and n and r is sufficiently large.

In many problems we need to calculate nCr%m where n, r and m are three positive integers. If the mod value m is a prime number then we can calculate nCr%m in different ways like using loops, using pascal’s triangle, using modular multiplicative inverse, using dp technique etc. This ways are described with source codes in this post.

Now our problem arrive when the mod value m is not prime. In this case we can’t use the above techniques. In this case we need to use the chinese remainder theorem (CRT) and Andrew Granville’s theory for calculating nCr. Here I provide you some ways to learn this techniques. I think this ways will be helpful to you.

1. First learn about chinese remainder theorem (CRT). You can learn it form these sources-
a. geeksforgeeks 1
b. geeksforgeeks 2
c. youtube 1
d. youtube 2

2. Second you can have a look on Andres Granville’s theory. The theory is explained here.

3. Now you can have a look on this problem. The detailed algorithm for our job is explained in this problem’s editorial section.

4. Now you can try to implement the algorithm. If you find any difficulties after several tries then you can see my implementation. Which is given below.


#include <bits/stdc++.h>

#define pii              pair <int,int>
#define pll              pair <long long,long long>
#define sc               scanf
#define pf               printf
#define Pi               2*acos(0.0)
#define ms(a,b)          memset(a, b, sizeof(a))
#define pb(a)            push_back(a)
#define MP               make_pair
#define db               double
#define ll               long long
#define EPS              10E-10
#define ff               first
#define ss               second
#define sqr(x)           (x)*(x)
#define D(x)             cout<<#x " = "<<(x)<<endl
#define VI               vector <int>
#define DBG              pf("Hi\n")
#define MOD              1000000007
#define CIN              ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define SZ(a)            (int)a.size()
#define sf(a)            scanf("%d",&a)
#define sfl(a)           scanf("%lld",&a)
#define sff(a,b)         scanf("%d %d",&a,&b)
#define sffl(a,b)        scanf("%lld %lld",&a,&b)
#define sfff(a,b,c)      scanf("%d %d %d",&a,&b,&c)
#define sfffl(a,b,c)     scanf("%lld %lld %lld",&a,&b,&c)
#define stlloop(v)       for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define loop(i,n)        for(int i=0;i<n;i++)
#define loop1(i,n)       for(int i=1;i<=n;i++)
#define REP(i,a,b)       for(int i=a;i<b;i++)
#define RREP(i,a,b)      for(int i=a;i>=b;i--)
#define TEST_CASE(t)     for(int z=1;z<=t;z++)
#define PRINT_CASE       printf("Case %d: ",z)
#define LINE_PRINT_CASE  printf("Case %d:\n",z)
#define CASE_PRINT       cout<<"Case "<<z<<": "
#define all(a)           a.begin(),a.end()
#define intlim           2147483648
#define infinity         (1<<28)
#define ull              unsigned long long
#define gcd(a, b)        __gcd(a, b)
#define lcm(a, b)        ((a)*((b)/gcd(a,b)))

using namespace std;


//----------------------Graph Moves----------------
//const int fx[]={+1,-1,+0,+0};
//const int fy[]={+0,+0,+1,-1};
//const int fx[]={+0,+0,+1,-1,-1,+1,-1,+1};   // Kings Move
//const int fy[]={-1,+1,+0,+0,+1,+1,-1,-1};  // Kings Move
//const int fx[]={-2, -2, -1, -1,  1,  1,  2,  2};  // Knights Move
//const int fy[]={-1,  1, -2,  2, -2,  2, -1,  1}; // Knights Move
//------------------------------------------------

//-----------------------Bitmask------------------
//int Set(int N,int pos){return N=N | (1<<pos);}
//int reset(int N,int pos){return N= N & ~(1<<pos);}
//bool check(int N,int pos){return (bool)(N & (1<<pos));}
//------------------------------------------------

#define mx 1000006

bitset<mx/2>vis;
vector<int>prime;

vector<pii>factor;

void sieve()
{
    int x=mx/2,y=sqrt(mx)/2;
    for(int i=1; i<=y; i++)
    {
        if(vis[i]==0)
        {
            for(int j=i*(i+1)*2; j<x; j+=(2*i)+1)
                vis[j]=1;
        }
    }

    prime.pb(2);

    for(int i=3; i<mx; i+=2)
        if(vis[i/2]==0)
            prime.pb(i);

}

ll factorial[mx];
ll arr[mx];


vector<ll>ans;

void precal(ll p, ll q, ll mod)
{
    arr[0]=1;
    arr[1]=1;
//    ll mod=bigmod(p,q,MOD);
    ll x=1;
    for(ll i=2; i<=mod; i++)
    {
        if(i%p)
            x=i;
        else
            x=1;
        arr[i]=(arr[i-1]*x)%mod;
    }
}

ll bigmod(ll n, ll p, ll mod)
{
    ll ret=1;
    while(p)
    {
        if(p%2)
            ret=(ret*n)%mod;
        n=(n*n)%mod;
        p/=2;
    }
    return ret;
}

ll E(ll n, ll p)
{
    ll ret=0;
    while(n)
    {
        ret+=n/p;
        n=n/p;
    }
    return ret;
}

ll f(ll n, ll mod)
{
    ll ret=bigmod(arr[mod-1],n/mod,mod)*arr[n%mod];
    return ret;
}

ll F(ll n, ll mod, ll p)
{
    ll ret=1;
    ll i=1;
    while(i<=n)
    {
        ret=(ret*f(n/i,mod))%mod;
        i=i*p;
    }
    return ret;
}

int inv(int a, int m) // Calculating Modular Multiplicative Inverse
{
    int m0 = m, t, q;
    int x0 = 0, x1 = 1;

    if (m == 1)
        return 0;

//     Apply extended Euclid Algorithm
    while (a > 1)
    {
//         q is quotient
        q = a / m;

        t = m;

//         m is remainder now, process same as
//         euclid's algo
        m = a % m, a = t;

        t = x0;

        x0 = x1 - q * x0;

        x1 = t;
    }

//     Make x1 positive
    if (x1 < 0)
        x1 += m0;

    return x1;
}




ll nCr(ll n, ll r, ll p, ll mod)
{
    ll e=E(n,p)-E(r,p)-E(n-r,p);
    ll mod1=F(n,mod,p);
    ll mod2=(F(r,mod,p)*F(n-r,mod,p))%mod;
    mod2=inv(mod2,mod);
    ll ret=bigmod(p,e,mod);
    ret*=mod1;
    ret%=mod;
    ret*=mod2;
    ret%=mod;
    return ret;
}

ll findMinX(int k) // Chinese Remainder
{
    ll prod = 1;
    vector<int>num;
    for(int i=0; i<k; i++)
    {
        num.pb(bigmod(factor[i].ff,factor[i].ss,MOD));
    }
    for (int i = 0; i < k; i++)
        prod *= num[i];

    ll result = 0;

    for (int i = 0; i < k; i++)
    {
        ll pp = prod / num[i];
        result += ans[i] * inv(pp, num[i]) * pp;
    }

    return result % prod;
}

ll nCr_mod_m(ll n, ll r, ll m)
{
    factor.clear();
    ans.clear();
    int root=sqrt(m);
    ll mm=m;
    for(int i=0; i<SZ(prime) && prime[i]<=root; i++)
    {
        if(mm%prime[i]==0)
        {
            int cnt=0;
            while(mm%prime[i]==0)
            {
                mm/=prime[i];
                cnt++;
            }
            factor.pb(pii(prime[i],cnt));
            root=sqrt(mm);
        }
    }

    if(mm>1)
        factor.pb(pii(mm,1));



    for(int i=0; i<SZ(factor); i++)
    {
        ll p=factor[i].ff;

        ll num=bigmod(p,factor[i].ss,MOD);
        precal(p,factor[i].ss,num);
        ans.pb(nCr(n,r,p,num));
    }

    ll anss=findMinX(SZ(factor));
    return anss;
}

int main()
{

//    freopen("in.txt","r",stdin);
//	  freopen("out.txt","w",stdout);

    sieve();

    int t;
    sf(t);
    TEST_CASE(t)
    {
        ll n,r,m;
        cin>>n>>r>>m;

        ll ans=nCr_mod_m(n,r,m);

        pf("%lld C %lld mod %lld = %lld\n",n,r,m,ans);
    }

    return 0;
}


Practice problems:
1. nCr
2. Codechef’s Long Sandwich(SANDWICH).

UVa 11246 – K-Multiple Free set

Problem Link : https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=2203

Solution Idea:


int MFS(int N,int K)
{
int ret=0;
for(int i=1;N;i=-i)
{
ret+=N*i;
N/=K;
}
return ret;
}

So how does this work? Let us start with the full set {1…N}. We need to remove some numbers from this so that it is a K-multiple free set. For this, let us remove every multiple of K from the set. These are the numbers K,2K… and there are N/K of them. Removing them gives us a K-multiple free set. But we have removed some numbers unnecessarily. Since we already removed K, removing K² was unnecessary. Thus we can put back K²,2K²…, which would be N/K² numbers in total. But this ends up putting both K² and K³ into the set and we need to remove all multiples of K³ now. Proceeding in this fashion, it is easy to see that the cardinality of the final set is N – N/K + N/K² – N/K³…

In general, an input size of N=10⁹ in a mathematical problem should give you the idea that neither the time or space complexity of the solution can be O(N) and you have to come up with some sort of a closed form solution.

This solutino idea is from this link.


#include <bits/stdc++.h>

#define pii              pair <int,int>
#define pll              pair <long long,long long>
#define sc               scanf
#define pf               printf
#define Pi               2*acos(0.0)
#define ms(a,b)          memset(a, b, sizeof(a))
#define pb(a)            push_back(a)
#define MP               make_pair
#define db               double
#define ll               long long
#define EPS              10E-10
#define ff               first
#define ss               second
#define sqr(x)           (x)*(x)
#define D(x)             cout<<#x " = "<<(x)<<endl
#define VI               vector <int>
#define DBG              pf("Hi\n")
#define MOD              1000000007
#define CIN              ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define SZ(a)            (int)a.size()
#define sf(a)            scanf("%d",&a)
#define sfl(a)           scanf("%lld",&a)
#define sff(a,b)         scanf("%d %d",&a,&b)
#define sffl(a,b)        scanf("%lld %lld",&a,&b)
#define sfff(a,b,c)      scanf("%d %d %d",&a,&b,&c)
#define sfffl(a,b,c)     scanf("%lld %lld %lld",&a,&b,&c)
#define stlloop(v)       for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define loop(i,n)        for(int i=0;i<n;i++)
#define loop1(i,n)       for(int i=1;i<=n;i++)
#define REP(i,a,b)       for(int i=a;i<b;i++)
#define RREP(i,a,b)      for(int i=a;i>=b;i--)
#define TEST_CASE(t)     for(int z=1;z<=t;z++)
#define PRINT_CASE       printf("Case %d: ",z)
#define LINE_PRINT_CASE  printf("Case %d:\n",z)
#define CASE_PRINT       cout<<"Case "<<z<<": "
#define all(a)           a.begin(),a.end()
#define intlim           2147483648
#define infinity         (1<<28)
#define ull              unsigned long long
#define gcd(a, b)        __gcd(a, b)
#define lcm(a, b)        ((a)*((b)/gcd(a,b)))

using namespace std;


/*----------------------Graph Moves----------------*/
//const int fx[]={+1,-1,+0,+0};
//const int fy[]={+0,+0,+1,-1};
//const int fx[]={+0,+0,+1,-1,-1,+1,-1,+1};   // Kings Move
//const int fy[]={-1,+1,+0,+0,+1,+1,-1,-1};  // Kings Move
//const int fx[]={-2, -2, -1, -1,  1,  1,  2,  2};  // Knights Move
//const int fy[]={-1,  1, -2,  2, -2,  2, -1,  1}; // Knights Move
/*------------------------------------------------*/

/*-----------------------Bitmask------------------*/
//int Set(int N,int pos){return N=N | (1<<pos);}
//int reset(int N,int pos){return N= N & ~(1<<pos);}
//bool check(int N,int pos){return (bool)(N & (1<<pos));}
/*------------------------------------------------*/


int main()
{

//    freopen("in.txt","r",stdin);
//	  freopen("out.txt","w",stdout);

    int t;
    sf(t);
    TEST_CASE(t)
    {
        ll n,k;
        sffl(n,k);
        if(k==0)
            pf("0\n");
        else
        {
            ll ans=n;
            ll kk=k;
            int cnt=1;
            while(kk<=n)
            {
                if(cnt%2)
                    ans-=(n/kk);
                else
                    ans+=(n/kk);
                kk*=k;
                cnt++;
            }
            pf("%lld\n",ans);
        }
    }

    return 0;
}