Submission #358477

#TimeUsernameProblemLanguageResultExecution timeMemory
358477CaroLindaBoat (APIO16_boat)C++14
100 / 100
625 ms4588 KiB
#include <bits/stdc++.h>

#define debug printf
#define all(x) x.begin(),x.end()
#define ll long long
#define sz(x) x.size() 

const int MAXN = 1010 ;
const ll MOD = 1e9+7 ;

using namespace std ;

/* Quick description of the solution because I'm dumb and disorganized */

//dp[i][j] represents the possibilities given that I only have the boats [1;i] and the intervals [1;j]
//and is guaranteed that boat number i is going to be chosen
//For this problem, I had to come up with a little lemma (don't know if it is a well-known fact)
//(I don't do Math olympiads :P)
//Link to the "proof": https://pasteboard.co/JLhIM6E.jpg
//To find C(x+y, y) quickly, I did a trick: 
//C(x+y,y) = C(x+y-1,y-1) * (x+y)/y
//Because the inverses of 1, 2, ..., y are easily calculated in O(N)

int N , M ;
int A[MAXN] , B[MAXN] ;
int val[MAXN] ;
ll inv[MAXN] ;
ll dp[MAXN][MAXN] ;

int main()
{

	vector<int> compression ;
	inv[1] = 1 ;

	scanf("%d", &N ) ;
	for(int i = 1 ; i <= N ; i++ ) 
	{
		scanf("%d %d", &A[i], &B[i] ) ;

		compression.push_back(A[i]) ;
		compression.push_back( ++B[i] ) ;		 

		if( i > 1 )
		{
			inv[i] = ( (-MOD/i)*inv[MOD%i] ) % MOD ;
			if(inv[i] < 0 ) inv[i] += MOD ;
		}

	}

	sort(all(compression) ) ;
	compression.erase( unique(all(compression) ) , compression.end() ) ;

	M = sz(compression) ;

	for(int i = 0 ; i < M-1 ; i++ ) val[i+1] = compression[i+1] - compression[i] ;
	for(int i= 1 ; i <= N ; i++ ) 
	{
		A[i] = lower_bound(all(compression) , A[i] ) - compression.begin() +1 ;
		B[i] = lower_bound(all(compression) , B[i] ) - compression.begin() + 1 ;
	}

	for(int j = 0 ; j < M ; j++ ) dp[0][j] = 1LL ;
	ll ans = 0LL ;

	for(int i = 1; i <= N ; i++ )
	{

		for(int j = A[i] ; j < B[i] ; j++ )
		{			

			//In the beginning, cnt is C(val[j]+0, 0+1)
			ll cnt = val[j] , y = 1 ;
			ll x = val[j] ;	

			for(int person = i-1 ; person >= 0 ; person-- )
			{
				dp[i][j] += (cnt * dp[person][j-1] ) % MOD ;
				if( dp[i][j] >= MOD ) dp[i][j] -= MOD ;

				if( A[person] <= j && B[person] > j )
				{
					++x , ++y ;					
					cnt = ( ( cnt * x ) % MOD * inv[y] ) % MOD ; 
				}

			}
				
			
		}

		for(int j = 1 ; j < M ; j++ ) 
		{
			dp[i][j] += dp[i][j-1] ;
			if( dp[i][j] >= MOD ) dp[i][j] -= MOD ;
		}

		ans += dp[i][M-1] ;
		if(ans >= MOD ) ans -= MOD ;
		
	}

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

}

Compilation message (stderr)

boat.cpp: In function 'int main()':
boat.cpp:36:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   36 |  scanf("%d", &N ) ;
      |  ~~~~~^~~~~~~~~~~
boat.cpp:39:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   39 |   scanf("%d %d", &A[i], &B[i] ) ;
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...