#P (sharp-P) is the class of counting problems: given a verifier for an NP problem, count how many accepting paths exist. Computing the exact count is at least as hard as deciding membership. #P-complete problems include counting satisfying assignments, perfect matchings, and Hamiltonian cycles—most of which have no known polynomial-time algorithms.
Study the contrast between decision (SAT ∈ NP) and counting (#SAT ∈ #P). Show that counting perfect matchings is #P-complete even though perfect matching decision is in P.
You already know that NP captures decision problems — questions with yes/no answers where a "yes" witness can be verified quickly. SAT asks: is there *any* satisfying assignment to a Boolean formula? The corresponding counting problem, #SAT, asks: *how many* satisfying assignments are there? This shift from existence to enumeration defines the class #P (pronounced "sharp-P"). Where NP problems accept nondeterministic paths that "guess" a solution, a #P problem counts the total number of accepting nondeterministic paths.
The surprising depth of #P emerges from problems where deciding is easy but counting is hard. Consider perfect matchings in a bipartite graph: you can decide whether one exists in polynomial time using standard matching algorithms. But counting the *number* of perfect matchings — computing the permanent of the adjacency matrix — is #P-complete. Valiant proved this in 1979. The permanent looks almost identical to the determinant formula (replace all minus signs with plus signs), yet computing the determinant is in P while computing the permanent is #P-hard. This shows that #P-hardness is not a failure of algorithmic ingenuity but a structural property of the problem.
The relationship between #P and the classes you know from the polynomial hierarchy is indirect but important. #P sits "above" NP in hardness: any #P function is at least as hard as any NP decision problem. Formally, Toda's theorem (1991) shows that the entire polynomial hierarchy PH reduces to P^#P — a single query to a #P oracle can simulate any finite number of alternations between ∃ and ∀ quantifiers. This means counting solutions is strictly more powerful than deciding them, even with the full power of alternation.
Practical consequences are real. Bayesian inference in many graphical models reduces to computing a marginal probability — which amounts to counting weighted solutions. Monte Carlo approximations and FPRAS (fully polynomial randomized approximation schemes) are often the best known alternatives. For #P-complete problems, getting an exact answer is believed to be intractable, but approximate counting is sometimes feasible in polynomial time for problems where exact counting is hard. Understanding #P is therefore not just theoretical: it explains why exact probabilistic inference is computationally expensive and why approximation algorithms dominate in practice.
No topics depend on this one yet.