Apparently, this will not happen quickly with the above sequence - getting IEnumerable<double> as input will do very little.
However, if the sequence parameters are known, this problem can be approached analytically, without generating the sequence itself!
Your sequence, if you do not divide it by 0, is the same a * beta^i % m .
If beta is mutually simple with m, then, as follows from Fermat’s small theorem,
beta ^ (φ(m) - 1) % m = 1
In other words, the cycle is always there, it begins with the first element, and its length must be a divisor φ(m) - 1 , where φ is the Euler function.
Now that if beta is not mutually simple with m, then their common factor, once inside a, no longer “leaves” this variable. The loop has a prefix (it does not start with 1).
Thus, the criterion for the start of a cycle is the fact that gcd(a, m) = gcd(a*beta, m) , where gcd is the greatest common divisor:
// Алгоритм Евклида int gcd(int a, int b) { while (b > 0) { var c = a % b; a = b; b = c; } return a; } int first = 0; while (gcd(a, m) != gcd(a*beta, m)) { a = (a * beta) % m; first++; }
In principle, knowledge of the first element of the cycle is enough to find its repetition in a reasonable time. But if you want to dig deeper, you can go further. Now you can make an equivalent transformation of the remaining sequence, reducing a and m by their GCD - this does not change the length of the cycle, but allows you to use the formula:
int d = gcd(a, m); m /= d; a /= d;
Now it remains to go through the dividers φ(m) - 1 and find among them the length of the cycle (for example, using the fast exponentiation algorithm). Here, the easiest way is to start with the obviously suitable length φ(m) - 1 and try to divide it into all simple dividers smaller than square root, each time checking the cycle using quick exponentiation.
The total running time is O (M ^ 1 * log M), that is, a time on the order of 2 ^ 21. In the special case when M is a power of two, it is still much simpler and only O ((log M) ^ 2) remains (and knowing in advance that M is a power of two, you can write the algorithm quite simply, dispensing with even the Euclidean algorithm).
mapproximately? A simple method returns exactlymunique values:0/m,1/m, ...,(m-1)/m, since0 <= a < m, as I understand it. - Dmitry D.m? 10, 100, 1000, .., 2 ^ 30? - Dmitry D.