Challenge: Cycle Representation
Subdomeniu: Combinatorics (combinatorics)
Scor cont: 120.0 / 120
Submission status: Accepted
Submission score: 1.0
Submission ID: 464775637
Limbaj: cpp14
Link challenge: https://www.hackerrank.com/challenges/cycle-representation/problem
Cerinta
Let $n$ be a fixed integer. <br>
A **permutation** is a bijection from the set $\{1,2,\ldots,n\}$ to itself. <Br><br>
A **cycle of length $k$** ($k\ge 2$) is a permutation $f$ where different integers exist $i_1,\ldots,i_k$ such that $f(i_1)=i_2, f(i_2)=i_3, \ldots, f(i_k)=i_1$ and, for all $x$ not in $\{i_1,\ldots,i_k\}$, $f(x)=x$.
The **composition of $m$ permutations** $f_1,\ldots,f_m$, written $f_1\circ f_2\circ\ldots\circ f_m$, is their composition as functions.
Steve has some cycles $f_1,f_2,\ldots,f_m$. He knows the length of cycle $f_i$ is $l_i$, but he does not know exactly what the cycles are.
He finds that the composition $f_1\circ f_2\circ\ldots\circ f_m$ of the cycles is a cycle of length $n$. <br>
He wants to know how many possibilities of $f_1,\ldots,f_m$ exist.
Input Format
The first line contains $T$, the number of test cases. <br>
Each test case contains the following information:<br>
The first line of each test case contains two space separated integers, $n$ and $m$.<br>
The second line of each test case contains $m$ integers, $l_1,\ldots,l_m$.
**Constraints**
$n \geqslant 2$
Sum of $n\leqslant 1000$
$2\leqslant l_i \leqslant n$
Sum of $m\le 10^6$
Output Format
Output $T$ lines. Each line contains a single integer, the answer to the corresponding test case.
Since the answers may be very large, output them modulo $(10^9+7)$.
Cod sursa
#include <bits/stdc++.h>
using namespace std;
#define int64 unsigned long long int
int64 prime = 1000000007ULL;
int64 bin[1001][1001];
int64 binsum[1001][1001];
int cs[1001][1001];
int64 power(int64 abase, int64 aexp){
int64 base = abase;
int64 exp = aexp;
int64 res=1;
while(exp > 0ULL){
if(exp % 2ULL == 1ULL) res = (res * base) % prime;
base = (base * base) % prime;
exp /= 2ULL;
}
return res % prime;
}
int64 fast_chi(int n, int m, int c){
if(c == n){
if((m + 1) % 2 == 0) return 1ULL;
else return (prime - 1ULL);
}
else{
int lower_limit;
int upper_limit;
if((c <= m) && (c <= (n - m + 1))){
lower_limit = 1;
upper_limit = c;
}
else if((c > m) && (c <= (n - m + 1))){
lower_limit = 1;
upper_limit = m;
}
else if((c <= m) && (c > (n - m + 1))){
lower_limit = c - (n - m);
upper_limit = c;
}
else{
lower_limit = c - (n - m);
upper_limit = m;
}
int64 lower_sum = 0ULL;
int64 upper_sum = 0ULL;
int64 answer;
for(int x = lower_limit; x < (upper_limit + 1); x += 2)
lower_sum = (lower_sum + bin[n - c][m - x]) % prime;
if(lower_limit < upper_limit)
for(int x = lower_limit+1; x < (upper_limit + 1); x += 2)
upper_sum = (upper_sum + bin[n - c][m - x]) % prime;
if((lower_limit + 1) % 2 == 0)
answer = (lower_sum + ((upper_sum * (prime - 1)) % prime)) % prime;
else answer = (upper_sum + ((lower_sum * (prime - 1)) % prime)) % prime;
int64 banswer = binsum[n - c][m - lower_limit];
if(upper_limit < m)
banswer += (((prime - 1) * binsum[n - c][m - upper_limit - 1]) % prime);
if(m % 2 == 0) banswer = (banswer * (prime - 1)) % prime;
return banswer;
}
}
int64 chi(int n, int m, int c){
if(2 * m < (n + 1)){
if(c == 1) return bin[n - 1][m - 1];
else if(c <= m){
int64 total = 0ULL;
for(int i = 0; i < c; i++){
int x = i + 1;
if((x + 1) % 2 == 0) total = (total + bin[n - c][m - x]) % prime;
else{
int64 add = (bin[n - c][m - x] * (prime - 1ULL)) % prime;
total = (total + add) % prime;
}
}
return total;
}
else if((c > m) && (c <= (n - m + 1))){
int64 total = 0ULL;
for(int i = 0; i < m; i++){
int x = i + 1;
if((x + 1) % 2 == 0) total = (total + bin[n - c][m - x]) % prime;
else{
int64 add = (bin[n - c][m - x] * (prime - 1ULL)) % prime;
total = (total + add) % prime;
}
}
return total;
}
else if((c > (n - m + 1)) && (c < n)){
int64 total = 0ULL;
for(int x = c - (n - m); x < (m + 1); x++){
if((x + 1) % 2 == 0) total = (total + bin[n - c][m - x]) % prime;
else{
int64 add = (bin[n - c][m - x] * (prime - 1ULL)) % prime;
total = (total + add) % prime;
}
}
return total;
}
else{
if((m + 1) % 2 == 0) return 1ULL;
else return (prime - 1ULL);
}
}
else{
if(c == 1) return bin[n - 1][m - 1];
else if(c <= (n - m + 1)){
int64 total = 0ULL;
for(int i = 0; i < c; i++){
int x = i + 1;
if((x + 1) % 2 == 0) total = (total + bin[n - c][m - x]) % prime;
else{
int64 add = (bin[n - c][m - x] * (prime - 1ULL)) % prime;
total = (total + add) % prime;
}
}
return total;
}
else if((c > (n - m + 1)) && (c <= m)){
int64 total = 0ULL;
for(int x = c - (n - m); x < (c + 1); x++){
if((x + 1) % 2 == 0) total = (total + bin[n - c][m - x]) % prime;
else{
int64 add = (bin[n - c][m - x] * (prime - 1ULL)) % prime;
total = (total + add) % prime;
}
}
return total;
}
else if((c > m) && (c < n)){
int64 total = 0ULL;
for(int x = c - (n - m); x < (m + 1); x++){
if((x + 1) % 2 == 0) total = (total + bin[n - c][m - x]) % prime;
else{
int64 add = (bin[n - c][m - x] * (prime - 1ULL)) % prime;
total = (total + add) % prime;
}
}
return total;
}
else{
if((m + 1) % 2 == 0) return 1ULL;
else return (prime - 1ULL);
}
}
}
int64 get_trace(int n, int m, int trial){
int64 total = 1;
int64 len_c = 0ULL;
for(int i = 0; i < 1001; i++){
int exponent = cs[trial][i];
if(exponent > 0){
int64 base = fast_chi(n, m, i);
int64 ull_exp = (int64) exponent;
len_c += ull_exp;
int64 multiplier = power(base, ull_exp);
total = (total * multiplier) % prime;
}
}
int64 dimension = fast_chi(n, m, 1);
total = (total * dimension) % prime;
total = (total * chi(n, m, n)) % prime;
int64 divisor = power(dimension, len_c);
total = (total * power(divisor, prime-2)) % prime;
return total;
}
int64 get_conjugacy_class_size(int n, int c){
if(c == 1) return 1ULL;
else{
int64 total = bin[n][c];
for(int i = 1; i < c; i++){
int64 multiplier = (int64) i;
total = (total * multiplier) % prime;
}
return total;
}
}
int64 get_multiplier(int n, int trial){
int64 long_n = (int64) n;
int64 answer = power(long_n, prime - 2ULL);
for(int i = 0; i < 1001; i++){
int exponent = cs[trial][i];
if(exponent > 0){
int64 long_exp = (int64) exponent;
int64 base = get_conjugacy_class_size(n, i);
answer = (answer * power(base, long_exp)) % prime;
}
}
return answer;
}
int64 get_enumeration(int n, int trial){
int64 total = 0ULL;
for(int i = 1; i < (n + 1); i++) total = (total + get_trace(n, i, trial)) % prime;
int64 mult = get_multiplier(n, trial); total = (total * mult) % prime;
return total;
}
int main(){
int T; cin >> T;
for(int i = 0; i < T; i++)
for(int j = 0; j < T; j++)
cs[i][j] = 0;
int ns[T]; int ms[T];
for(int i = 0; i < T; i++){
int m; cin >> ns[i] >> m; ms[i] = m;
for(int j = 0; j < m; j++){
int k; cin >> k;
cs[i][k] += 1;
}
}
int max_n = 0;
for(int i = 0; i < T; i++) if(ns[i] > max_n) max_n = ns[i];
for(int i = 0; i < (max_n + 1); i++){
for(int j = 0; j < (i + 1); j++){
if(j ==0) bin[i][j] = 1ULL;
else if(j == i) bin[i][j] = 1ULL;
else bin[i][j] = (bin[i - 1][j] + bin[i - 1][j - 1]) % prime;
}
}
for(int i = 0; i < (max_n + 1); i++){
for(int j = 0; j < (i + 1); j++){
if(j ==0) binsum[i][j] = 1ULL;
else {
int64 adder;
if(j % 2 == 0) adder = bin[i][j];
else adder = (bin[i][j] * (prime - 1)) % prime;
binsum[i][j] = (binsum[i][j-1] + adder) % prime;
}
}
}
for(int i = 0; i < T; i++){
int64 answer = get_enumeration(ns[i], i);
cout << answer << endl;
}
return 0;
}
HackerRank Combinatorics – Cycle Representation
