1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| public class Combination
{
private long n = 0;
private long k = 0;
private long[] data = null;
public Combination(long n, long k)
{
if (n < 0 || k < 0) // normally n >= k
throw new Exception("Negative parameter in constructor");
this.n = n;
this.k = k;
this.data = new long[k];
for (long i = 0; i < k; ++i)
this.data[i] = i;
} // Combination(n,k)
public Combination(long n, long k, long[] a) // Combination from a[]
{
if (k != a.Length)
throw new Exception("Array length does not equal k");
this.n = n;
this.k = k;
this.data = new long[k];
for (long i = 0; i < a.Length; ++i)
this.data[i] = a[i];
if (!this.IsValid())
throw new Exception("Bad value from array");
} // Combination(n,k,a)
public bool IsValid()
{
if (this.data.Length != this.k)
return false; // corrupted
for (long i = 0; i < this.k; ++i)
{
if (this.data[i] < 0 || this.data[i] > this.n - 1)
return false; // value out of range
for (long j = i+1; j < this.k; ++j)
if (this.data[i] >= this.data[j])
return false; // duplicate or not lexicographic
}
return true;
} // IsValid()
public override string ToString()
{
string s = "{ ";
for (long i = 0; i < this.k; ++i)
s += this.data[i].ToString() + " ";
s += "}";
return s;
} // ToString()
public Combination Successor()
{
if (this.data[0] == this.n - this.k)
return null;
Combination ans = new Combination(this.n, this.k);
long i;
for (i = 0; i < this.k; ++i)
ans.data[i] = this.data[i];
for (i = this.k - 1; i > 0 && ans.data[i] == this.n - this.k + i; --i)
;
++ans.data[i];
for (long j = i; j < this.k - 1; ++j)
ans.data[j+1] = ans.data[j] + 1;
return ans;
} // Successor()
public static long Choose(long n, long k)
{
if (n < 0 || k < 0)
throw new Exception("Invalid negative parameter in Choose()"); if (n < k)
return 0; // special case
if (n == k)
return 1;
long delta, iMax;
if (k < n-k) // ex: Choose(100,3)
{
delta = n-k;
iMax = k;
}
else // ex: Choose(100,97)
{
delta = k;
iMax = n-k;
}
long ans = delta + 1;
for (long i = 2; i <= iMax; ++i)
{
checked { ans = (ans * (delta + i)) / i; } }
return ans;
} // Choose()
} // Combination class |
Partager