PROBLEM LINK:
Author: Satyam Gupta
Tester: Pulkit Sharma
Editorialists: Satyam Gupta,Pulkit Sharma
DIFFICULTY:
MEDIUM
PREREQUISITES:
Maths, Combinatorics, Inclusion-Exclusion Principle
PROBLEM:
There are R types of orbs. There are equal number of orbs of all types.
Each orb is unique in itself. Count the no. of ways to choose k orbs that includes at least one orb from all R types.
EXPLANATION:
Count the no. of ways of choosing k orbs, such that there exists at least one type for which no orb is selected and subtract from the total no. of ways of choosing k orbs. To calculate this, use Inclusion-Exclusion Principle.
Initially, let answer=0 and then, to the answer:
i) Add no. of ways to select k orbs.
ii) Subtract no. of ways of selecting k orbs, where exactly one type exists for which no orb is selected.
iii) Add no. of ways of selecting k orbs, where exactly two types exist for which no orb is selected.
iv) Subtract no. of ways of selecting k orbs, where exactly three types exist for which no orb is selected.
… and so on.
So,
Here is the pseudocode implementing the above said procedure
y=n/r
ans = 0
for i=0 to r:
if(i%2=1)
ans = ans - ncr(r,i)*ncr(n-i*y,k)
else
ans = ans + ncr(r,i)*ncr(n-i*y,k)
//ncr(a,b) calculates a choose b (Binomial Coefficient)
return ans
Complexity of this solution:
Preprocessing for calculating factorials and modular inverse of factorials (used for computing ^nC_r ): O(100000)
Final complexity = O(R + 100000)
AUTHOR’S AND TESTER’S SOLUTIONS:
#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 1000000007
#define ll long long int
ll fact[1001],ifact[1001];
ll modpow(ll base, ll exponent, int modulus=MOD)
{
ll result = 1;
while (exponent > 0)
{
if (exponent % 2 == 1)
result = (result * base) % modulus;
exponent = exponent >> 1;
base = (base * base) % modulus;
}
return result;
}
ll modinv(ll x)
{
return modpow(x,MOD-2);
}
void calc()
{
fact[0]=fact[1]=ifact[0]=ifact[1]=1;
for(int i=2;i<=1000;i++)
{
fact[i]=(fact[i-1]*i)%MOD;
ifact[i]=(ifact[i-1]*modinv(i))%MOD;
}
}
ll ncr(ll n,ll r)
{
if(n<r) return 1;
return (((fact[n]*ifact[n-r])%MOD)*ifact[r])%MOD;
}
int main()
{
ll t,n,r,k,i,y,ans;
calc();
cin>>t;
while(t--)
{
cin>>n>>r>>k;
y=n/r;
ans = 0;
for(i=0;i<r;i++)
{
if(i&1)
ans = ((ans - (ncr(r,i)*ncr(n - i*y,k))%MOD)+MOD)%MOD;
else
ans = (ans + (ncr(r,i)*ncr(n - i*y,k))%MOD)%MOD;
printf("(%ld,%ld)\n",ncr(r,i),ncr(n - i*y,k));
}
cout<<ans<<endl;
}
return 0;
}