Farmer John has come up with a new morning exercise routine for the cows (again)!
As before, Farmer John's NN cows (1≤N≤75001≤N≤7500) are standing in a line. The ii-th cow from the left has label ii for each 1≤i≤N1≤i≤N. He tells them to repeat the following step until the cows are in the same order as when they started.
For example, if A=(1,2,3,4,5)A=(1,2,3,4,5) then the cows perform one step and immediately return to the same order. If A=(2,3,1,5,4)A=(2,3,1,5,4), then the cows perform six steps before returning to the original order. The order of the cows from left to right after each step is as follows:
Compute the product of the numbers of steps needed over all N!N! possible permutations AA of length NN.
As this number may be very large, output the answer modulo MM (108≤M≤109+7108≤M≤109+7, MM is prime).
Contestants using C++ may find the following code from KACTL helpful. Known as the Barrett reduction, it allows you to compute a%ba%b several times faster than usual, where b>1b>1 is constant but not known at compile time. (we are not aware of such an optimization for Java, unfortunately).
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; typedef __uint128_t L; struct FastMod { ull b, m; FastMod(ull b) : b(b), m(ull((L(1) << 64) / b)) {} ull reduce(ull a) { ull q = (ull)((L(m) * a) >> 64); ull r = a - q * b; // can be proven that 0 <= r < 2*b return r >= b ? r - b : r; } }; FastMod F(2); int main() { int M = 1000000007; F = FastMod(M); ull x = 10ULL*M+3; cout << x << " " << F.reduce(x) << "\n"; // 10000000073 3 }
The first line contains NN and MM.
A single integer.
5 1000000007
369329541
For each 1≤i≤N1≤i≤N, the ii-th element of the following array is the number of permutations that cause the cows to take ii steps: [1,25,20,30,24,20].[1,25,20,30,24,20]. The answer is 11⋅225⋅320⋅430⋅524⋅620≡369329541(mod109+7)11⋅225⋅320⋅430⋅524⋅620≡369329541(mod109+7).
Note: This problem has an expanded memory limit of 512 MB.
Problem credits: Benjamin Qi
[/hide]
(Analysis by Benjamin Qi, Sanjeev Murty)
Call the number of steps that a permutation requires the period of the permutation. Every permutation can be partitioned into cycles of sizes c1,c2,c3,…,ckc1,c2,c3,…,ck such that c1+c2+…+ck=Nc1+c2+…+ck=N. Then the period is equal to lcm(c1,c2,…,ck)lcm(c1,c2,…,ck).
Subtask N≤50N≤50:
Maintain the number of possible permutations for each possible LCM of a permutation with nn elements for each 1≤n≤N1≤n≤N. This number is quite small for N=50N=50 (it ends up being 1056) but grows quite rapidly. The number of permutations for a single LCM should be stored (modM−1)(modM−1) because aM−1≡1(modM)aM−1≡1(modM) for all 0<a<M0<a<M (Fermat's Little Theorem).
Subtask N≤500N≤500:
In general, we can calculate the period of a permutation as follows:
So we can essentially solve the problem independently for each distinct prime power DD. Doing this in O(N2)O(N2) for a single prime power is sufficient for this subtask.
Subtask N≤3000N≤3000:
If we can count the number of ways to create a permutation of length nn for each n∈[1,N]n∈[1,N] such that no cycle length is divisible by DD in O(N2D)O(N2D) time, then the solution runs in O(N2⋅∑ND=11D)=O(N2logN)O(N2⋅∑D=1N1D)=O(N2logN) time.
Subtask N≤7500N≤7500:
The high bound on NN (hopefully) ensures that the above solution does not receive full credit. How can we do better?
Note that if 2D>N2D>N then we can compute the number of permutations containing a cycle with length divisible by DD in O(1)O(1) time (assuming that we have precomputed some quantities in O(N2)O(N2)). This is true because if there is a cycle with length divisible by pkpk, then there must be exactly one cycle with length equal to pkpk (and the rest can have arbitrary lengths).
Let's try to generalize. Define D=pkD=pk. Any permutation has between 00 and ⌊ND⌋⌊ND⌋ cycles with length divisible by DD. So it suffices to count each of the following quantities for each k∈[0,⌊ND⌋]k∈[0,⌊ND⌋].
If we can count both of these in O(N2D2)O(N2D2) time, then this solution runs in O(N2⋅∑∞D=11D2)=O(N2⋅π26)=O(N2)O(N2⋅∑D=1∞1D2)=O(N2⋅π26)=O(N2) time.
Mark Chen's code:
#include <bits/stdc++.h> using namespace std; typedef long long LL; int n; LL m; typedef unsigned long long ull; typedef __uint128_t L; struct FastMod { ull b, m; FastMod(ull b) : b(b), m(ull((L(1) << 64) / b)) {} ull reduce(ull a) { ull q = (ull)((L(m) * a) >> 64); ull r = a - q * b; // can be proven that 0 <= r < 2*b return r >= b ? r - b : r; } }; FastMod f(2); LL mul(LL x, LL y) { return f.reduce(x * y); } LL add(LL x, LL y) { x += y; if (x >= m) x -= m; return x; } LL sub(LL x, LL y) { x -= y; if (x < 0) x += m; return x; } LL powmod(LL a, LL b) {LL res=1; a %= (m+1); for(;b;b>>=1) {if (b&1) res = res*a % (m+1); a = a*a % (m+1);} return res;} const int MAXN = 7505; LL factorial[MAXN], c[MAXN][MAXN]; int main() { freopen("exercise.in","r",stdin); freopen("exercise.out","w",stdout); cin >> n >> m; m--; f = FastMod(m); factorial[0] = 1; for (int i = 1; i < MAXN; ++i) factorial[i] = mul(factorial[i-1], i); c[1][0] = c[1][1] = 1; for (int i = 2; i < MAXN; i++) { c[i][0] = c[i][i] = 1; for (int j = 1; j < i; j++) c[i][j] = add(c[i-1][j-1], c[i-1][j]); } vector<int> composite(MAXN); LL ans = 1; for (int i = 2; i <= n; i++) { if (!composite[i]) { for (int j = i; j <= n; j *= i) { // count permutations of length j*k where ALL cycles are divisible by j vector<LL> aj(n/j+1); aj[0] = 1; for (int k = 1; k < n/j+1; k++) { for (int l = 1; l <= k; l++) { aj[k] = add(aj[k], mul(mul(c[j*k-1][j*l-1], factorial[j*l-1]), aj[k-l])); } } // count permutations of length n-j*k where NO cycle is divisible by j vector<LL> nj(n/j+1); for (int k = n/j; k >= 0; k--) { nj[k] = factorial[n-j*k]; for (int l = k+1; l <= n/j; l++) { nj[k] = sub(nj[k], mul(c[n-j*k][n-l*j], mul(aj[l-k], nj[l]))); } } ans = (ans * powmod(i, sub(factorial[n], nj[0]))) % (m+1); } for (int j = 2*i; j <= n; j += i) { composite[j] = 1; } } } printf("%lld\n", ans); }
My code (which uses the principle of inclusion and exclusion):
#include <bits/stdc++.h> using namespace std; void setIO(string s) { ios_base::sync_with_stdio(0); cin.tie(0); freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } typedef long long ll; const int MX = 7501; typedef unsigned long long ul; typedef __uint128_t L; struct ModFast { ul b, m; ModFast(ul b) : b(b), m(ul((L(1)<<64)/b)) {} ul reduce(ul a) { ul q = (ul)((L(m)*a)>>64), r = a-q*b; return r>=b?r-b:r; } }; ModFast MF(1); int M,MOD,n; int ad(int a, int b) { a += b; if (a >= M) a -= M; return a; } int sub(int a, int b) { a -= b; if (a < 0) a += M; return a; } int mul(int a, int b) { return MF.reduce((ul)a*b); } int choose[MX][MX]; int with(int z) { // # of permutations with z dividing some cycle length int res = 0; vector<int> dp(n/z+1); dp[0] = sub(0,1); for (int i = 1; i <= n/z; ++i) for (int j = 1; j <= i; ++j) dp[i] = sub(dp[i],mul(choose[i*z-1][j*z-1],dp[i-j])); for (int i = 1; i <= n/z; ++i) res = ad(res,mul(choose[n][n-i*z],dp[i])); return res; } ll mpow(ll a, ll b) { return !b?1:mpow(a*a%MOD,b/2)*(b&1?a:1)%MOD; } int main() { setIO("exercise"); cin >> n >> MOD; M = MOD-1; MF = ModFast(M); for (int i = 0; i <= n; ++i) { choose[i][0] = 1; for (int j = 0; j < i; ++j) choose[i][j+1] = mul(choose[i][j],i-j); } vector<bool> comp(n+1); ll ans = 1; for (int i = 2; i <= n; ++i) if (!comp[i]) { for (int j = 2*i; j <= n; j += i) comp[j] = 1; for (int j = i; j <= n; j *= i) ans = ans*mpow(i,with(j))%MOD; } cout << ans << "\n"; }
It is possible to solve this problem more quickly if you are familiar with exponential generating functions (EGF). This comment gives an explicit formula, which I'll try to explain here. From KACTL, we have the following fact. Let gS(n)gS(n) be the number of nn-permutations whose cycle lengths all belong to the set SS. Letting S(x)=∑n∈SxnnS(x)=∑n∈Sxnn, it follows that
Essentially, the S(x)kk!S(x)kk! term corresponds to the number of ways to form permutations with exactly kk cycles. When all cycle lengths are valid,
and
which is clearly correct. If we want to exclude cycles with lengths that are multiples of zz, then
It follows that
By the binomial theorem, the numerator has only terms with degree divisible by zz. Letting d=⌊n/z⌋d=⌊n/z⌋ and [xn]P(x)[xn]P(x) denote the coefficient of xnxn in P(x)P(x), it follows that
By the binomial theorem,
So it turns out that we can replace part of the above code with
int without(int z) { int res = 1; for (int i = 1; i <= n; ++i) { if (i%z != 0) res = mul(res,i); else res = mul(res,i-1); } return res; } int with(int z) { // # of permutations with z dividing some cycle length return sub(choose[n][n],without(z)); }
although this isn't actually faster since it still runs in O(Nπ(N))=O(N2/logN)O(Nπ(N))=O(N2/logN) time (where π(N)π(N) denotes the number of primes that are at most NN).
Here is a way to derive this formula without generating functions (by Sanjeev):
(BEGIN)
We use (n)k(n)k to denote n⋅(n−1)⋯(n−k+1)n⋅(n−1)⋯(n−k+1), the falling factorial.
Let anan be the number of permutations that have no cycles with length dividing zz. Then, if we imagine choosing the rest of the cycle that 11 belongs to then recursing, we have
Expressing this in terms of an−zan−z, we have
You can think of the above as two cases: we choose a cycle of length greater than zz or less than zz.
Now consider the corresponding expression for an−1an−1:
If we subtract n−1n−1 times this expression from the expression for anan, we get
This already implies an O(nπ(n))O(nπ(n)) algorithm for the original problem after pre-computation, but we can do better. Manipulating the above, we see
From the initial conditions, we see that bnbn is only nonzero when z∣nz∣n. It is then straightforward by induction that bn=an−1bn=an−1 when z∣nz∣n, so we have
If we precompute n!z⌊n/z⌋⌊n/z⌋!n!z⌊n/z⌋⌊n/z⌋! for all prime powers z≤nz≤n (noting that it is an integer), then after that we have an
algorithm for the problem. First factorize M−1M−1 in O(M−−√)O(M) time (or O(n)O(n), since prime factors of M−1M−1 greater than nn do not affect our answer). Then we can do this precomputation in O(nlogM)O(nlogM) time by looping in increasing order of zz and keeping track of the powers of the various prime factors of M−1M−1 in n!⌊n/z⌋!n!⌊n/z⌋!, in addition to the part of it sharing no prime factors with M−1M−1. For each prime power z=pkz=pk, if it is coprime to M−1M−1, we simply multiply n!⌊n/z⌋!n!⌊n/z⌋! by z−⌊n/z⌋modM−1z−⌊n/z⌋modM−1. Otherwise, we subtract k⌊n/z⌋k⌊n/z⌋ from the exponent of pp we have been keeping track of. Our final time complexity (assuming a word size of Ω(max(logn,logM))Ω(max(logn,logM))) is then
and we require O(n)O(n) space. The space can probably be improved to O(n/logn)O(n/logn). Note that the constant factor for logMlogM is favorable, since it comes from the maximum number of primes dividing M−1M−1 (e.g. 99 for M≤109M≤109).
(END)
Another solution that runs in O(NlogN)O(NlogN) time is to use divide and conquer to initialize a data structure that allows you to query any range product l⋅(l+1)⋯(r−1)⋅rl⋅(l+1)⋯(r−1)⋅r modulo M−1M−1 in constant time (where 1≤l≤r≤N1≤l≤r≤N). This avoids the need to factorize M−1M−1.
[/hide]
© 2024. All Rights Reserved. 沪ICP备2023009024号-1