Farmer John has?NN?(1≤N≤3000)(1≤N≤3000)?cows of various sizes. He originally built each cow a personalized barn, but now some of the cows have outgrown their barns. Specifically, FJ originally built?NN?barns of sizes?t1,t2,…,tNt1,t2,…,tN, while the cows are now of sizes?s1,s2,…,sNs1,s2,…,sN?(1≤si,ti≤1091≤si,ti≤109).
Every night, the cows go through a ritual of finding a barn to sleep in. A cow?ii?can sleep in a barn?jj?if and only if they fit within the barn (si≤tjsi≤tj). Each barn can house at most one cow.
We say that a matching of cows to barns is?maximal?if and only if every cow assigned to a barn can fit in the barn, and every unassigned cow is incapable of fitting in any of the empty barns left out of the matching.
Compute the number of maximal matchings mod?109+7109+7.
The first line contains?NN.The second line contains?NN?space-separated integers?s1,s2,…,sNs1,s2,…,sN.
The third line contains?NN?space-separated integers?t1,t2,…,tNt1,t2,…,tN.
The number of maximal matchings mod?109+7109+7.
4 1 2 3 4 1 2 2 3
9
Here is a list of all nine maximal matchings. An ordered pair?(i,j)(i,j)?means that cow?ii?is assigned to barn?jj.
(1, 1), (2, 2), (3, 4) (1, 1), (2, 3), (3, 4) (1, 1), (2, 4) (1, 2), (2, 3), (3, 4) (1, 2), (2, 4) (1, 3), (2, 2), (3, 4) (1, 3), (2, 4) (1, 4), (2, 2) (1, 4), (2, 3)
Problem credits: Nick Wu
[/hide]
(Analysis by Nick Wu)
Subtask 1:
A naive brute-force solution involves enumerating all possible maximal matchings, which if implemented well should take?O(N!?N)O(N!?N)?time.
Subtask 2:
For a solution that runs in polynomial time, we can start by sorting the cows and barns in nondecreasing size order. If we fix the smallest cow that is not in the matching (if any), then we can count the number of matchings satisfying this condition in?O(N2)O(N2)?time by doing a DP storing the number of cows / barns we have processed so far as well as the number of cows we assert will be included in the final matching and still need to match.
When we process a cow, we can either include it in the matching or not. If we include it, then we increment the number of cows to match by one. Cows smaller than the smallest cow that is not in the matching must be included.
When we process a barn, we can either try to match it with a cow that needs to be matched or not. Barns greater than the smallest cow that is not in the matching must be included.
This should run in?O(N3)O(N3)?time.
Subtask 3:
We can optimize this down to?O(N2)O(N2)?time. Instead of iterating over all possible smallest unmatched cows, we'll store an additional piece of information in our DP state - a boolean flag representing whether all cows we have seen so far will be included in the final matching. When we decide not to include a cow in the matching, we set this flag to be true. We can only decide not to include a barn in the matching when the flag is false (otherwise, we can match an ignored cow with the current barn, contradicting the maximality property).
This DP ultimately has?O(N2)O(N2)?states and?O(1)O(1)?transitions per state, to get us to the desired runtime of?O(N2)O(N2).
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); int n = Integer.parseInt(br.readLine()); Event[] events = new Event[2*n]; for(int a = 0; a < 2; a++) { StringTokenizer st = new StringTokenizer(br.readLine()); for(int i = 0; i < n; i++) { events[a*n+i] = new Event(Integer.parseInt(st.nextToken()), a); } } Arrays.sort(events); final int MOD = 1000000007; int[][] dp = new int[n+1][2]; dp[0][0] = 1; int[][] ndp = new int[n+1][2]; for(Event e: events) { for(int i = 0; i <= n; i++) Arrays.fill(ndp[i], 0); if(e.type == 0) { // cow for(int a = 0; a < n; a++) { for(int j = 0; j < 2; j++) { ndp[a+1][j] += dp[a][j]; if(ndp[a+1][j] >= MOD) ndp[a+1][j] -= MOD; ndp[a][1] += dp[a][j]; if(ndp[a][1] >= MOD) ndp[a][1] -= MOD; } } } else { for(int a = 0; a < n; a++) { if(a > 0) { for(int j = 0; j < 2; j++) { ndp[a-1][j] += (a * (long)dp[a][j]) % MOD; if(ndp[a-1][j] >= MOD) ndp[a-1][j] -= MOD; } } ndp[a][0] += dp[a][0]; } } for(int i = 0; i <= n; i++) { dp[i][0] = ndp[i][0]; dp[i][1] = ndp[i][1]; } } pw.println((dp[0][0] + dp[0][1]) % MOD); pw.close(); } static class Event implements Comparable<Event> { public int size, type; public Event(int a, int b) { size = a; type = b; } public int compareTo(Event s) { if(size != s.size) { return size - s.size; } return type - s.type; } } }
[/hide]
? 2025. All Rights Reserved. 沪ICP备2023009024号-1