# INQU2004-Editorial

Practice
Contest
Author:- Gaurav Katare
Tester:- Vivek Rathi

Easy-Medium

# PREREQUISITES:

matrix expo,combinatorics

# Problem:

There are two options:

• Choose some number k. Considering all coins identical, give kk coins to Chotua. Next, treat remaining n−k coins as distinct and give k coins to Expert. Lets say there are p1 ways to do so for all possible k.
• Choose some number k. Considering all coins distinct, give k coins to Chotua. Next ,treat remaining n−k coins as identical and give k coins to =Expert. Lets say there are p2 ways to do so for all possible k.

Calculate the ratio of p1 and p2 . As this number can be rather large,he asks you to count the remainder after dividing it with 109+7

# Explanation:

Since we have to distribute k coins to both friends so k belongs to [0,floor(n/2)].

Let find the value of p2, number of ways to distribute the k coins to both friends such that first all coins are distinct and then remaining n-k coins are identical are \binom{n}{k}.
So p2 = \sum_{k=1}^{N/2} \binom{n}{k}

As we know that \binom{n}{0} +…\binom{n}{n}= 2^n. For even numbers there are odd numbers of terms and for odd numbers there are even numbers of terms. In question it is mentioned that n is odd so we have exactly half of the terms, so \binom{n}{0}+\binom{n}{1}. +…\binom{n}{n/2} = 2^{n-1} . Since N is large we will use modular exponentiation.

Now let’s find the value of p1, number of ways to distribute the k coins to both friends such that first all coins are identical and then remaining n-k coins are distinct are \binom{n-k}{k}.

So p1=\sum_{k=1}^{N/2} \binom{n-k}{k}

For calculation of p1 construct pascal triangle.

\binom{0}{0}

\binom{1}{0} \binom{1}{1}

\binom{2}{0} \binom{2}{1} \binom{2}{2}

\binom{3}{0} \binom{3}{1} \binom{3}{2} \binom{3}{3}

\binom{4}{0} \binom{4}{1} \binom{4}{2} \binom{4}{3} \binom{4}{4}

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

We can observe that summation of diagonals of pascal’s triangle are in the form of Fibonacci and our equation is one of the diagonal . Hence p1=[N+1]th Fibonacci term. Since N is large so we can matrix exponential to calculate fibonacci terms.

The ratio of (p1/p2) \bmod 1000000007 will be the answer.

# Time Complexity

Time Complexity per testcase is O(log(n))

# Solution

Setter's Solution
/*
Gaurav Katare
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define sz(x)	(ll)x.size()
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#define endl '\n'
//unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
//shuffle (foo.begin(), foo.end(), std::default_random_engine(seed));
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
ll res=1;
while(b)
{
if(b&1LL)
res=(res*a)%c;
a=(a*a)%c;
b>>=1;
}
return res;
}
//-------------------------------Template--Above-----------------------------------------------
struct matrix
{
#define SZ 2 // change here for matrix size
ll ar[SZ][SZ];
void reset()
{
memset(ar,0,sizeof(ar));
}
void makeidentity()
{
for(int i=0;i<SZ;i++)
{
for(int j=0;j<SZ;j++)
{
if(i==j)
ar[i][j]=1;
else
ar[i][j]=0;
}
}
}
{
matrix res;
for(int i=0;i<SZ;i++)
{
for(int j=0;j<SZ;j++)
{
res.ar[i][j] = (ar[i][j] +o.ar[i][j])%M;
}
}
return res;
}
{
matrix res;
res.reset();
for(int i=0;i<SZ;i++)
{
for(int j=0;j<SZ;j++)
{
for(int k=0;k<SZ;k++)
{
res.ar[i][j]=(res.ar[i][j]+(ar[i][k]*o.ar[k][j])%M)%M;
}
}
}
return res;
}
matrix power(matrix a,ll b)
{
matrix res;
res.makeidentity();
while(b)
{
if(b&1)
{
res=res*a;
}
a=a*a;
b>>=1;
}
return res;
}
};

int main()
{
boost
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
matrix m;
m.ar[0][0]=1,m.ar[0][1]=1;
m.ar[1][0]=1,m.ar[1][1]=0;
matrix sol=m.power(m,n-1);
ll ans=(sol.ar[0][0]+sol.ar[0][1])%M;
//debug1(ans2);
cout<<(ans*modpower(modpower(2,n-1,M),M-2,M))%M<<endl;
}
return 0;
}

Tester's Solution
#include <bits/stdc++.h>
#include <algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ass 1e18
#define MOD 1000000007
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define debug(x) cout << #x << ": " << x << endl;
#define debug2(x,y) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<< endl;
#define debug3(x,y,z) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<<" "<<#z<<" : "<<z<< endl;
using namespace std;
typedef long long int ll;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>

ll modpower(ll a,ll b,ll c)
{
ll res=1;
while(b)
{
if(b&1LL)
res=(res*a)%c;
a=(a*a)%c;
b>>=1;
}
return res;
}

struct matrix
{
#define SZ 2 // change here for matrix size
ll ar[SZ][SZ];
void reset()
{
memset(ar,0,sizeof(ar));
}
void makeidentity()
{
for(int i=0;i<SZ;i++)
{
for(int j=0;j<SZ;j++)
{
if(i==j)
ar[i][j]=1;
else
ar[i][j]=0;
}
}
}
{
matrix res;
for(int i=0;i<SZ;i++)
{
for(int j=0;j<SZ;j++)
{
res.ar[i][j] = (ar[i][j] +o.ar[i][j])%MOD;
}
}
return res;
}
{
matrix res;
res.reset();
for(int i=0;i<SZ;i++)
{
for(int j=0;j<SZ;j++)
{
for(int k=0;k<SZ;k++)
{
res.ar[i][j]=(res.ar[i][j]+(ar[i][k]*o.ar[k][j])%MOD)%MOD;
}
}
}
return res;
}
matrix power(matrix a,ll b)
{
matrix res;
res.makeidentity();
while(b)
{
if(b&1)
{
res=res*a;
}
a=a*a;
b>>=1;
}
return res;
}
};

void solve()
{
ll n;
cin>>n;
matrix m;
m.ar[0][0]=1,m.ar[0][1]=1;
m.ar[1][0]=1,m.ar[1][1]=0;
m=m.power(m,n-1);
ll ans1=(((m.ar[0][0])%MOD)+((m.ar[0][1])%MOD))%MOD;
ll ans2=modpower(2,n-1,MOD);
cout<<(ans1*modpower(ans2,MOD-2,MOD))%MOD<<"\n";
}

int main()
{
boost
ll t=1;
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
cin>>t;
while(t--)
{
solve();
}
return 0;
}

1 Like