Expense Sharing Calculation
The main issue I can see, is the excessive use of generic data types like tuples and dictionaries instead of domain classes. That may be a matter of taste, but I prefer meaningful named domain classes like your Account class. 
In the Account class, the dictionary is exposed as public member. IMHO internal data structures should be encapsulated. The class should be extended by appropriated methods to manipulate that data structures. That would automatically move code like



if (debtors.ContainsKey(transaction.Item1))
{
    debtors[transaction.Item1] += transaction.Item2;
}
else
{
    debtors.Add(transaction.Item1, transaction.Item2);
}



into the domain class. Imagine use have to add items somewhere else, that kind of code must be duplicated each time.


Instead of


if (!beneficiary.Equals(transaction.Item1))
{
    ...
}




You could use

 if (beneficiary.Equals(transaction.Item1))
 {
     continue;
 }

 ....


to reduce nesting.


The instance variable debtors should be read-only.
Another small point: I would use strings to store the users because you can store names and you do not run into problems if the group becomes greater than 26 persons :P - of course, that is not relevant for the algorithm.




Generall Approach

Your approach is, to build up two dictionaries (the ledger and the debtors within the account class). The data structure of nested dictionaries matches the requirements exactly. If the requirements change, you have to restructure your whole code.

It is better to transform the data in a simple generally usable data structure and implement your algorithm for that data structure.

Such a simple data structure may be a list of Transactions:

public class Transaction
{
    public Transaction(string payer, string payee, int amount)
    {
        Payer = payer;
        Amount = amount;
        Payee = payee;
    }

    public string Payer { get; }
    public int Amount { get; }
    public string Payee { get; }
}


The algorithms could be implemented in a class like Bank:

public class Bank
{
    private readonly List&lt;Transaction&gt; myTransactions = new List&lt;Transaction&gt;();
    private readonly HashSet&lt;string&gt; myPayers = new HashSet&lt;string&gt;();
    private readonly HashSet&lt;string&gt; myPayees = new HashSet&lt;string&gt;();

    public void AddTransaction(string payer, string payee, int amount) 
    {
        myTransactions.Add(new Transaction(payer, payee, amount));
        myPayers.Add(payer);
        myPayees.Add(payee);
    }

    public void PrintPayees()
    {
        foreach (var payee in myPayees)
        {
            var trans = myTransactions.Where(t =&gt; t.Payee == payee);
            Console.WriteLine($"User {payee} owes ${trans.Sum(t =&gt; t.Amount)} total:");
            foreach (var groupedTransaction in trans.GroupBy(t =&gt; t.Payer))
                Console.WriteLine($"- ${groupedTransaction.Sum(t =&gt; t.Amount)} from {groupedTransaction.Key}");
        }
    }

    public void PrintPayer()
    {
        foreach (var payer in myPayers)
        {
            var trans = myTransactions.Where(t =&gt; t.Payer == payer);
            Console.WriteLine($"User {payer} gets ${trans.Sum(t =&gt; t.Amount)} total:");
            foreach (var groupedTransaction in trans.GroupBy(t =&gt; t.Payee))
                Console.WriteLine($"- ${groupedTransaction.Sum(t =&gt; t.Amount)} to {groupedTransaction.Key}");
        }
    }
}


Usage base on the list of tuples:

void Main()
{
    var bank = new Bank();

    foreach (var transaction in new[] { Tuple.Create("A", 100, new [] { "A", "B", "C", "D" }),
                                        Tuple.Create("D", 500, new [] { "B", "C" }),
                                        Tuple.Create("B", 300, new [] { "A", "B", "C" }) })
    {
        var payer = transaction.Item1;
        var amount = transaction.Item2;
        foreach (var payee in transaction.Item3)
            if (payee != payer)
                bank.AddTransaction(payer, payee, amount);
    }   

    bank.PrintPayees();
    bank.PrintPayer();
}