![HackerRank Cards Permutation Problem Solution](https://thecscience.com/wp-content/uploads/2023/05/HackerRank-Cards-Permutation-Problem-Solution.jpg)
HackerRank Cards Permutation Problem Solution
In this post, we will solve HackerRank Cards Permutation Problem Solution.
Alice was given then integers from 1 to n. She wrote all possible permutations in increasing lexicographical order, and wrote each permutation in a new line. For example, for n = 3, there are 6 possible permutations:
- [1, 2, 3]
- [1, 3, 2]
- [2, 1, 3]
- [2, 3, 1]
- [3, 1, 2]
- [3, 2, 1]
She then chose one permutation among them as her favorite permutation.
After some time, she forgot some elements of her favorite permutation. Nevertheless, she still tried to write down its elements. She wrote a 0) in every position where she forgot the true value.
She wants to know the sum of the line numbers of the permutations which could possibly be her favorite permutation, i.e., permutations which can be obtained by replacing the Os. Can you help her out?
Since the sum can be large, find it modulo 109 + 7.
Input Format
The first line contains a single integer n.
The next line contains n space-separated integers a1, a2,…, an denoting Alice’s favorite permutation with some positions replaced by 0.
Output Format
Print a single line containing a single integer denoting the sum of the line numbers of the permutations which could possibly be Alice’s favorite permutation.
Sample Input 0
4 0 2 3 0
Sample Output 0
23
Explanation 0
The possible permutations are [1, 2, 3, 4] and [4, 2, 3, 1]. The permutation [1, 2, 3, 4] occurs on line 1 and the permutation [4, 2, 3, 1] occurs on line 22. Therefore the sum is
1+22= 23.
Sample Input 1
4 4 3 2 1
Sample Output 1
24
Explanation 1
There is no missing number in the permutation. Therefore, the only possible permutation is
[4, 3, 2, 1], and it occurs on line 24. Therefore the sum is 24.
![HackerRank Cards Permutation Problem Solution](https://thecscience.com/wp-content/uploads/2023/05/HackerRank-Cards-Permutation-Problem-Solution-1024x576.jpg)
Cards Permutation C Solution
#include<stdio.h>
int n, a[300100], pos[300100],
mod = 1e9 + 7, occ[300100],
les[300100], grt[300100], st[300100],
lst[300100], gst[300100], bitree[300050];
void add(int idx, int val)
{
while( idx <= n )
{
bitree[idx] += val;
idx += ( idx & -idx );
}
}
int get(int idx)
{
int ans = 0;
while( idx > 0 )
{
ans += bitree[idx];
idx -= ( idx & -idx );
}
return ans;
}
long long fact[300100], factsumfr[300100], ans = 0;
long long pwr(long long a, long long b)
{
if( b == 0 )
{
return 1ll;
}
long long temp = pwr(a, b/2);
temp = ( temp * temp ) % mod;
if( b & 1 )
{
temp = ( temp * a ) % mod;
}
return temp;
}
long long inv(long long a)
{
return pwr(a, mod-2);
}
int main()
{
int i;
scanf("%d", &n);
for( i = 1 ; i <= n ; i++ )
{
scanf("%d", &a[i]);
pos[a[i]] = i;
if(a[i])
{
st[a[i]] = 1;
}
if(a[i])
{
occ[i] = 1;
}
}
fact[0] = 1;
for( i = 1 ; i <= n ; i++ )
{
les[i] = les[i-1] + occ[i], lst[i] =
lst[i-1] + st[i], fact[i] = ( fact[i-1] * i ) % mod;
}
for( i = n ; i >= 1 ; i-- )
{
grt[i] = grt[i+1] + occ[i], gst[i] = gst[i+1] + st[i];
}
int k = les[n];
long long faci = fact[n-k],
faci1 = fact[n-k-1], sumfrfr = 0;
for( i = 1 ; i <= n ; i++ )
{
if( a[i] == 0 )
{
sumfrfr = ( sumfrfr + ( ( fact[n-i] * (
n - i - grt[i+1] ) ) % mod * inv(n-k-1) ) % mod ) % mod;
factsumfr[i] = (
factsumfr[i-1] + fact[n-i] ) % mod;
}
else
{
factsumfr[i] = factsumfr[i-1];
}
}
for( i = 1 ; i <= n ; i++ )
{
long long inc = 0;
if( st[i] == 0 )
{
inc += ( inc + ( ( sumfrfr * ( i - 1 - lst[i] )
) % mod * fact[n-k-1] ) % mod ) % mod;
}
else
{
inc = ( inc + ( ( ( n - i + 1 - gst[i] )
* factsumfr[pos[i]] ) % mod * fact[n-k-1] )
% mod ) % mod;
inc = ( inc + ( ( ( ( ( i - lst[i] )
* fact[n-pos[i]] ) % mod * fact[n-k] ) % mod * (
n - pos[i] + 1 - grt[pos[i]] ) ) % mod
* inv(n-k) ) % mod ) % mod;
add(pos[i], 1);
int inv1 = get(n) - get(pos[i]);
inc = ( inc + ( ( fact[n-pos[i]]
* fact[n-k] ) % mod * inv1 ) % mod ) % mod;
}
ans = ( ans + inc ) % mod;
}
ans = ( ans + fact[n-k] ) % mod;
printf("%lld\n", ans);
return 0;
}
Cards Permutation C++ Solution
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define up(i,j,n) for (int i = j; i <= n; i++)
#define down(i,j,n) for (int i = j; i >= n; i--)
#define cmax(a,b) a = ((a) > (b) ? (a) : (b))
#define cmin(a,b) a = ((a) < (b) ? (a) : (b))
#define cadd(a,b) a = add (a, b)
#define cpop(a,b) a = pop (a, b)
#define cmul(a,b) a = mul (a, b)
#define pii pair<int, int>
#define fi first
#define se second
#define SZ(x) (int)x.size()
#define Auto(i,node) for (int i = LINK[node]; i; i = e[i].next)
const int MAXN = 3e5 + 5;
const int oo = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int inv2 = (mod + 1) >> 1;
inline int add(int a, int b){a += b; return a >= mod ? a - mod : a;}
inline int pop(int a, int b){a -= b; return a < 0 ? a + mod : a;}
inline int mul(int a, int b){return 1LL * a * b % mod;}
int N, a[MAXN], fac[MAXN], pre[MAXN], cnt = 0, ans = 0, cur = 0, lex = 0;
namespace BIT{
int c[MAXN];
inline int lowbit(int i){return i & (-i);}
inline void upd(int o, int v){
for (int i = o + 1; i <= N; i += lowbit(i)) c[i] += v;
}
inline int calc(int o){
int sum = 0;
for (int i = o + 1; i >= 1; i -= lowbit(i)) sum += c[i];
return sum;
}
}using namespace BIT;
namespace solution{
int cal2(int n){return mul(mul(n, pop(n, 1)), inv2);}
void Prepare(){
scanf("%d", &N);
up (i, 1, N) scanf("%d", &a[i]);
up (i, 1, N) {
a[i]--;
cnt += (a[i] == -1);
if (a[i] >= 0) pre[a[i]] = 1;
}
fac[0] = 1;
up (i, 1, N) fac[i] = mul(i, fac[i - 1]);
up (i, 1, N - 1) pre[i] += pre[i - 1];
lex = mul(mul(N, pop(N, 1)), inv2);
up (i, 1, N) if (a[i] != -1) cpop(lex, a[i]);
}
void Solve(){
up (i, 1, N) {
if (a[i] != -1) {
int sum = mul(fac[cnt] , a[i] - calc(a[i]));
if (cnt >= 1) cpop(sum, mul(fac[cnt - 1], mul(cur, a[i] + 1 - pre[a[i]])));
cmul(sum, fac[N - i]);
cadd(ans, sum);
upd(a[i], 1);
cpop(lex, pop(N - 1 - a[i], pop(pre[N - 1], pre[a[i]])));
}else {
int sum = mul(lex, fac[cnt - 1]);
if (cnt >= 2) cpop(sum, mul(fac[cnt - 2], mul(cur, cal2(cnt))));
cmul(sum, fac[N - i]);
cadd(ans, sum);
cur++;
}
}
printf("%d\n", add(ans, fac[cnt]));
}
}
int main(){
using namespace solution;
Prepare();
Solve();
return 0;
}
Cards Permutation C Sharp Solution
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using static System.Array;
using static System.Math;
class Solution
{
private int n;
private int[] a;
private int[] missing;
private int[] zeroes;
private bool[] visited;
private HashSet<int> present;
private FenwickTree ft;
public void Solve()
{
n = Ni();
a = Ni(n);
zeroes = new int[n];
visited = new bool[n + 1];
int zeroCount = 0;
foreach (var v in a)
{
visited[v] = true;
if (v == 0) zeroCount++;
}
missing = new int[zeroCount];
int m = 0;
for (int i = 1; i <= n; i++)
{
if (visited[i] == false)
missing[m++] = i;
}
for (int i = 0; i < n; i++)
zeroes[i] = a[i] == 0 ? 1 : 0;
ft = new FenwickTree(n + 1);
long answer;
//answer = Dfs();
//WriteLine(answer);
answer = DistributionAlgorithm();
WriteLine(answer);
}
long DistributionAlgorithm()
{
long count = Fact(missing.Length);
long countm1 = missing.Length >= 1 ? Fact(missing.Length - 1) : 0;
long countm2 = missing.Length >= 2 ? Fact(missing.Length - 2) : 0;
long result = count;
int zeroes = 0;
long jsum = 0;
long osum = 0;
var mt = new RangeFenwick(missing.Length + 1);
var ft2 = new RangeFenwick(missing.Length + 1);
for (int j = 0; j < missing.Length; j++)
{
jsum += j;
osum += missing[j];
}
jsum %= MOD;
osum %= MOD;
for (int i = 0; i < n; i++)
{
var v = a[i];
var f = Fact(n - (i + 1));
var term = 0L;
if (v != 0)
{
ft.Add(v, 1);
int bound = Bound(missing, v, true);
mt.AddInclusive(bound, missing.Length, 1);
long ord = (v - ft.SumInclusive(v)) % MOD;
long add = (count * ord % MOD - ft2.SumInclusive(bound - 1)) % MOD;
term += add;
}
else
{
term = (osum - mt.SumInclusive(missing.Length - 1) - missing.Length) % MOD * countm1 % MOD;
term -= jsum * zeroes % MOD * countm2 % MOD;
term %= MOD;
ft2.AddInclusive(0, missing.Length - 1, countm1);
zeroes++;
}
while (term >= MOD) term -= MOD;
term = (term * f) % MOD;
result += term;
}
return Fix(result);
}
public class RangeFenwick
{
#region Variables
FenwickTree bit1; // Range Update; Point Query -- x coefficient
FenwickTree bit2; // Point Update; Range Query -- const
#endregion
#region Constructor
public RangeFenwick(int n)
{
bit1 = new FenwickTree(n);
bit2 = new FenwickTree(n);
}
#endregion
#region Properties
public int Length => bit1.Length;
public long this[int index] => QueryInclusive(index, index);
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public long[] Table
{
get
{
int n = Length;
long[] result = new long[n];
for (int i = 0; i < n; i++) result[i] = this[i];
return result;
}
}
#endregion
#region Methods
public void AddInclusive(int left, int right, long v)
{
if (left > right) return;
bit1.AltAddInclusive(left, right, v);
bit2.Add(left, -v * (left - 1) % MOD);
bit2.Add(right + 1, v * right % MOD);
}
// Range query: Returns the sum of all elements in [1...b]
public long SumInclusive(int i)
{
if (i < 0) return 0;
return (bit1.SumInclusive(i) * i % MOD + bit2.SumInclusive(i)) %MOD;
}
// Range query: Returns the sum of all elements in [i...j]
public long QueryInclusive(int i, int j)
{
return SumInclusive(j) - SumInclusive(i - 1);
}
#endregion
}
long Dfs(int index = 0, long rank = 1)
{
if (index == n)
return rank;
long result = 0;
var v = a[index];
if (v != 0)
{
ft.Add(v, 1);
var ord = v - ft.SumInclusive(v);
var newRank = rank + ord * Fact(n - (index + 1)) % MOD;
if (newRank >= MOD) newRank -= MOD;
result = Dfs(index + 1, newRank);
ft.Add(v, -1);
return result;
}
for (int i = 0; i < missing.Length; i++)
{
v = missing[i];
if (visited[v]) continue;
visited[v] = true;
ft.Add(v, 1);
var ord = v - ft.SumInclusive(v);
var newRank = rank + ord * Fact(n - (index + 1)) % MOD;
if (newRank >= MOD) newRank -= MOD;
result += Dfs(index + 1, newRank);
if (result >= MOD) result -= MOD;
ft.Add(v, -1);
visited[v] = false;
}
return result;
}
public class FenwickTree
{
#region Variables
public readonly long[] A;
#endregion
#region Constructor
/*public Fenwick(int[] a) : this(a.Length)
{
for (int i = 0; i < a.Length; i++)
Add(i, a[i]);
}*/
public FenwickTree(long[] a) : this(a.Length)
{
int n = a.Length;
System.Array.Copy(a, 0, A, 1, n);
for (int k = 2, h = 1; k <= n; k *= 2, h *= 2)
{
for (int i = k; i <= n; i += k)
A[i] += A[i - h];
}
//for (int i = 0; i < a.Length; i++)
// Add(i, a[i]);
}
public FenwickTree(long size)
{
A = new long[size + 1];
}
#endregion
#region Properties
public long this[int index] => AltRangeUpdatePointQueryMode ? SumInclusive(index) : SumInclusive(index, index);
public int Length => A.Length - 1;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public long[] Table
{
get
{
int n = A.Length - 1;
long[] ret = new long[n];
for (int i = 0; i < n; i++)
ret[i] = SumInclusive(i);
if (!AltRangeUpdatePointQueryMode)
for (int i = n - 1; i >= 1; i--)
ret[i] -= ret[i - 1];
return ret;
}
}
#endregion
#region Methods
// Increments value
/// <summary>
/// Adds val to the value at i
/// </summary>
/// <param name="i">The i.</param>
/// <param name="val">The value.</param>
public void Add(int i, long val)
{
if (val == 0) return;
for (i++; i < A.Length; i += (i & -i))
{
A[i] += val;
if (A[i] >= MOD)
A[i] -= MOD;
}
}
// Sum from [0 ... i]
public long SumInclusive(int i)
{
long sum = 0;
for (i++; i > 0; i -= (i & -i))
{
sum += A[i];
if (sum >= MOD)
sum -= MOD;
}
return sum;
}
public long SumInclusive(int i, int j)
{
return SumInclusive(j) - SumInclusive(i - 1);
}
// get largest value with cumulative sum less than x;
// for smallest, pass x-1 and add 1 to result
public int GetIndexGreater(long x)
{
int i = 0, n = A.Length - 1;
for (int bit = HighestOneBit(n); bit != 0; bit >>= 1)
{
int t = i | bit;
// if (t <= n && Array[t] < x) for greater or equal
if (t <= n && A[t] <= x)
{
i = t;
x -= A[t];
}
}
return i;
}
#endregion
#region Alternative Range Update Point Query Mode ( cf Standard Point Update Range Query )
public bool AltRangeUpdatePointQueryMode;
/// <summary>
/// Inclusive update of the range [left, right] by value
/// The default operation of the fenwick tree is point update - range query.
/// We use this if we want alternative range update - point query.
/// SumInclusive becomes te point query function.
/// </summary>
/// <returns></returns>
public void AltAddInclusive(int left, int right, long delta)
{
Add(left, delta);
Add(right + 1, -delta);
}
public long AltQuery(int index)
{
return SumInclusive(index);
}
#endregion
}
public class ArraySum
{
public readonly int[] _array;
public ArraySum(int[] array, bool inplace = false)
{
if (inplace == false)
array = (int[])array.Clone();
_array = array;
int sum = 0;
for (int i = 1; i < array.Length; i++)
{
array[i] += sum;
sum = array[i];
}
}
public int GetSum(int start, int count)
{
return GetSumInclusive(start, start + count - 1);
}
public int GetSumExclusive(int x1, int x2)
{
return GetSumInclusive(x1, x2 - 1);
}
public int GetSumInclusive(int x1, int x2)
{
int result = _array[x2];
if (x1 > 0) result -= _array[x1];
return result;
}
}
#region Mod Math
public const int MOD = 1000000007;
public const int FactCache = 3000001;
static int[] _inverse;
public static long Inverse(long n)
{
long result;
if (_inverse == null)
_inverse = new int[FactCache];
if (n < _inverse.Length && (result = _inverse[n]) != 0)
return result - 1;
result = ModPow(n, MOD - 2);
if (n < _inverse.Length)
_inverse[n] = (int)(result + 1);
return result;
}
public static long Mult(long left, long right)
{
return (left * right) % MOD;
}
public static long Div(long left, long divisor)
{
return left % divisor == 0
? left / divisor
: Mult(left, Inverse(divisor));
}
public static long Add(long x, long y)
{
return (x += y) >= MOD ? x - MOD : x;
}
public static long Subtract(long left, long right)
{
long result = left - right;
if (result < 0) result += MOD;
return result;
}
public static long Fix(long n)
{
return ((n % MOD) + MOD) % MOD;
}
public static long ModPow(long n, long p, long mod = MOD)
{
long b = n;
long result = 1;
while (p != 0)
{
if ((p & 1) != 0)
result = (result * b) % mod;
p >>= 1;
b = (b * b) % mod;
}
return result;
}
static List<long> _fact;
static List<long> _ifact;
public static long Fact(int n)
{
if (_fact == null) _fact = new List<long>(FactCache) { 1 };
for (int i = _fact.Count; i <= n; i++)
_fact.Add(Mult(_fact[i - 1], i));
return _fact[n];
}
public static long InverseFact(int n)
{
if (_ifact == null) _ifact = new List<long>(FactCache) { 1 };
for (int i = _ifact.Count; i <= n; i++)
_ifact.Add(Div(_ifact[i - 1], i));
return _ifact[n];
}
public static long Fact(int n, int m)
{
var fact = Fact(n);
if (m < n)
fact = Mult(fact, InverseFact(n - m));
return fact;
}
public static long Comb(int n, int k)
{
if (k <= 1) return k == 1 ? n : k == 0 ? 1 : 0;
if (k + k > n) return Comb(n, n - k);
return Mult(Mult(Fact(n), InverseFact(k)), InverseFact(n - k));
}
#endregion
#region Common
public static void Swap<T>(ref T a, ref T b)
{
var tmp = a;
a = b;
b = tmp;
}
public static void Clear<T>(T[] t, T value = default(T))
{
for (int i = 0; i < t.Length; i++)
t[i] = value;
}
public static int Bound<T>(T[] array, T value, bool upper = false)
where T : IComparable<T>
{
int left = 0;
int right = array.Length - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
int cmp = value.CompareTo(array[mid]);
if (cmp > 0 || cmp == 0 && upper)
left = mid + 1;
else
right = mid - 1;
}
return left;
}
public static long IntPow(long n, long p)
{
long b = n;
long result = 1;
while (p != 0)
{
if ((p & 1) != 0)
result = (result * b);
p >>= 1;
b = (b * b);
}
return result;
}
public static int Log2(long value)
{
if (value <= 0)
return value == 0 ? -1 : 63;
var log = 0;
if (value >= 0x100000000L)
{
log += 32;
value >>= 32;
}
if (value >= 0x10000)
{
log += 16;
value >>= 16;
}
if (value >= 0x100)
{
log += 8;
value >>= 8;
}
if (value >= 0x10)
{
log += 4;
value >>= 4;
}
if (value >= 0x4)
{
log += 2;
value >>= 2;
}
if (value >= 0x2)
{
log += 1;
}
return log;
}
public static int BitCount(long x)
{
int count;
var y = unchecked((ulong)x);
for (count = 0; y != 0; count++)
y &= y - 1;
return count;
}
public static int HighestOneBit(int n)
{
return n != 0 ? 1 << Log2(n) : 0;
}
#endregion
#region Fast IO
#region Input
static System.IO.Stream inputStream;
static int inputIndex, bytesRead;
static byte[] inputBuffer;
static System.Text.StringBuilder builder;
const int MonoBufferSize = 4096;
public static void InitInput(System.IO.Stream input = null, int stringCapacity = 16)
{
builder = new System.Text.StringBuilder(stringCapacity);
inputStream = input ?? Console.OpenStandardInput();
inputIndex = bytesRead = 0;
inputBuffer = new byte[MonoBufferSize];
}
static void ReadMore()
{
if (bytesRead < 0) throw new FormatException();
inputIndex = 0;
bytesRead = inputStream.Read(inputBuffer, 0, inputBuffer.Length);
if (bytesRead > 0) return;
bytesRead = -1;
inputBuffer[0] = (byte)'\n';
}
public static int Read()
{
if (inputIndex >= bytesRead) ReadMore();
return inputBuffer[inputIndex++];
}
public static T[] N<T>(int n, Func<T> func)
{
var list = new T[n];
for (int i = 0; i < n; i++) list[i] = func();
return list;
}
public static int[] Ni(int n)
{
var list = new int[n];
for (int i = 0; i < n; i++) list[i] = Ni();
return list;
}
public static long[] Nl(int n)
{
var list = new long[n];
for (int i = 0; i < n; i++) list[i] = Nl();
return list;
}
public static string[] Ns(int n)
{
var list = new string[n];
for (int i = 0; i < n; i++) list[i] = Ns();
return list;
}
public static int Ni()
{
var c = SkipSpaces();
bool neg = c == '-';
if (neg) { c = Read(); }
int number = c - '0';
while (true)
{
var d = Read() - '0';
if (unchecked((uint)d > 9)) break;
number = number * 10 + d;
if (number < 0) throw new FormatException();
}
return neg ? -number : number;
}
public static long Nl()
{
var c = SkipSpaces();
bool neg = c == '-';
if (neg) { c = Read(); }
long number = c - '0';
while (true)
{
var d = Read() - '0';
if (unchecked((uint)d > 9)) break;
number = number * 10 + d;
if (number < 0) throw new FormatException();
}
return neg ? -number : number;
}
public static char[] Nc(int n)
{
var list = new char[n];
for (int i = 0, c = SkipSpaces(); i < n; i++, c = Read()) list[i] = (char)c;
return list;
}
public static byte[] Nb(int n)
{
var list = new byte[n];
for (int i = 0, c = SkipSpaces(); i < n; i++, c = Read()) list[i] = (byte)c;
return list;
}
public static string Ns()
{
var c = SkipSpaces();
builder.Clear();
while (true)
{
if (unchecked((uint)c - 33 >= (127 - 33))) break;
builder.Append((char)c);
c = Read();
}
return builder.ToString();
}
public static int SkipSpaces()
{
int c;
do c = Read(); while (unchecked((uint)c - 33 >= (127 - 33)));
return c;
}
public static string ReadLine()
{
builder.Clear();
while (true)
{
int c = Read();
if (c == 10 || c == 13 && (c = Read()) == 10 || c <= 0) break;
builder.Append((char)c);
}
return builder.ToString();
}
#endregion
#region Output
static System.IO.Stream outputStream;
static byte[] outputBuffer;
static int outputIndex;
public static void InitOutput(System.IO.Stream output = null)
{
outputStream = output ?? Console.OpenStandardOutput();
outputIndex = 0;
outputBuffer = new byte[65535];
}
public static void Write(string format, params object[] args)
{
Write(string.Format(format, args));
}
public static void WriteLine(string format, params object[] args)
{
WriteLine(string.Format(format, args));
}
public static void WriteLine(object obj = null)
{
Write(obj);
Write('\n');
}
public static void WriteLine(long number)
{
Write(number);
Write('\n');
}
public static void Write(long signedNumber)
{
ulong number = unchecked((ulong)signedNumber);
if (signedNumber < 0)
{
Write('-');
number = unchecked((ulong)(-signedNumber));
}
Reserve(20 + 1); // 20 digits + 1 extra for sign
int left = outputIndex;
do
{
outputBuffer[outputIndex++] = (byte)('0' + number % 10);
number /= 10;
}
while (number > 0);
int right = outputIndex - 1;
while (left < right)
{
byte tmp = outputBuffer[left];
outputBuffer[left++] = outputBuffer[right];
outputBuffer[right--] = tmp;
}
}
public static void Write(object obj)
{
if (obj == null) return;
var s = obj.ToString();
Reserve(s.Length);
for (int i = 0; i < s.Length; i++)
outputBuffer[outputIndex++] = (byte)s[i];
}
public static void Write(char c)
{
Reserve(1);
outputBuffer[outputIndex++] = (byte)c;
}
public static void Write(byte[] array, int count)
{
Reserve(count);
Array.Copy(array, 0, outputBuffer, outputIndex, count);
outputIndex += count;
}
static void Reserve(int n)
{
if (outputIndex + n <= outputBuffer.Length)
return;
Dump();
if (n > outputBuffer.Length)
Array.Resize(ref outputBuffer, Math.Max(outputBuffer.Length * 2, n));
}
static void Dump()
{
outputStream.Write(outputBuffer, 0, outputIndex);
outputIndex = 0;
}
public static void Flush()
{
Dump();
outputStream.Flush();
}
#endregion
#endregion
#region Main
public static int Main()
{
try
{
InitInput(Console.OpenStandardInput());
InitOutput(Console.OpenStandardOutput());
new Solution().Solve();
Flush();
// Console.Error.WriteLine(Process.GetCurrentProcess().TotalProcessorTime);
return 0;
}
catch (Exception e)
{
Console.Error.WriteLine(e);
var line = new StackTrace(e, true).GetFrames()
.Select(x => x.GetFileLineNumber()).FirstOrDefault(x => x != 0);
var wait = line % 300 * 10 + 5;
var process = Process.GetCurrentProcess();
while (process.TotalProcessorTime.TotalMilliseconds > wait && wait < 3000) wait += 1000;
while (process.TotalProcessorTime.TotalMilliseconds < Math.Min(wait, 3000)) ;
return 1;
}
}
#endregion
}
Cards Permutation Java Solution
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class CardsPermutationFinal {
private final static long MOD = 1000000007;
private final static long INV_TWO = inverseElmnt(2);
private static final long Y_DISP = 10000000000l;
private static final Set<Long> USED_Y = new HashSet<>();
private static long pow(long n, long p) {
if (p == 0) {
return 1;
}
if (p % 2 == 0) {
return pow((n * n) % MOD, p / 2) % MOD;
} else {
return (n * pow(n, p - 1)) % MOD;
}
}
private static long inverseElmnt(long n) {
return pow(n, MOD - 2);
}
private static long fact(int n) {
long res = 1;
for(int i = 1; i <= n; i++) {
res = (res * i) % MOD;
}
return res;
}
private static long generateY() {
long y;
do {
y = (long)(Y_DISP * Math.random());
} while (USED_Y.contains(y));
USED_Y.add(y);
return y;
}
private long run(int n, int[] perm) {
int[] undefinedAmnt = new int[n];
undefinedAmnt[n - 1] = 0;
for (int i = n - 2; i >= 0; i--) {
undefinedAmnt[i] = undefinedAmnt[i + 1] + (perm[i + 1] == 0 ? 1 : 0);
}
int totalUndef = undefinedAmnt[0] + (perm[0] == 0 ? 1 : 0);
long[] bin = new long[n];
bin[n - 1] = 1;
long chisl = totalUndef;
long znam = 1;
long[] incr = new long[n];
incr[n - 1] = 0;
long currentIncr = perm[n - 1] == 0 ? 1 : 0;
int chislForIncr = totalUndef - 1;
int znamForIncr = 1;
for (int i = n - 2; i >= 0; i--) {
if (undefinedAmnt[i] == undefinedAmnt[i + 1]) {
bin[i] = bin[i + 1];
} else {
bin[i] = (((bin[i + 1] * chisl) % MOD) * inverseElmnt(znam))% MOD;
chisl--;
znam++;
}
if (perm[i] != 0) {
incr[i] = perm[i + 1] != 0 ? incr[i + 1] : currentIncr;
} else {
if (0 == currentIncr) {
currentIncr = 1;
} else {
currentIncr = (((currentIncr * chislForIncr) % MOD) * inverseElmnt(znamForIncr)) % MOD;
chislForIncr--;
znamForIncr++;
}
}
}
long[] colSum = new long[n];
long[] rowSum = new long[n];
int cell = n - 1;
while (cell >= 0 && perm[cell] != 0) {
cell--;
}
if (cell >= 0) {
colSum[cell] = 1;
rowSum[cell] = totalUndef;
}
int chislColSum = totalUndef - 1;
int znamColSum = 1;
int chislRowSum = totalUndef - 1;
int znamRowSum = 2;
for (int i = cell - 1; i >= 0; i--) {
if (perm[i] == 0) {
colSum[i] = (((colSum[i + 1] * chislColSum) % MOD) * inverseElmnt(znamColSum)) % MOD;
chislColSum--;
znamColSum++;
rowSum[i] = (((rowSum[i + 1] * chislRowSum) % MOD) * inverseElmnt(znamRowSum)) % MOD;
chislRowSum--;
znamRowSum++;
} else {
colSum[i] = colSum[i + 1];
rowSum[i] = rowSum[i + 1];
}
}
int[] lessAmntLeft = new int[n + 1];
cell = n - 1;
while (cell >= 0 && perm[cell] == 0) {
cell--;
}
Treap t = null;
if (cell >= 0) {
t = new Treap(perm[cell], generateY(), null, null);
}
for (int i = cell - 1; i >= 0; i--) {
if (perm[i] != 0) {
Treap res = new Treap(perm[i], generateY(), null, null);
Treap[] splitRes = t.split(perm[i]);
lessAmntLeft[perm[i]] = splitRes[0] == null ? 0 : splitRes[0].size;
if (null != splitRes[0]) {
res = merge(splitRes[0], res);
}
if (null != splitRes[1]) {
res = merge(res, splitRes[1]);
}
t = res;
}
}
int[] defVals = new int[n - totalUndef];
int defValsSize = 0;
for (int i = 0; i < n; i++) {
if (perm[i] != 0) {
defVals[defValsSize] = perm[i];
defValsSize++;
}
}
Arrays.sort(defVals);
long[] greaterUndef = new long[n + 1];
long[] smallerDefined = new long[n + 1];
long totalSum = 0;
for (int i = 0; i < defValsSize; i++) {
int definedValue = defVals[i];
int greaterCnt = n - definedValue - (defValsSize - i - 1);
greaterUndef[definedValue] = greaterCnt;
totalSum = (totalSum + greaterCnt) % MOD;
smallerDefined[definedValue] = i;
}
long[] resultInpt = new long[n];
for (int i = n - 1; i >= 0; i--) {
if (perm[i] != 0) {
resultInpt[i] = (((incr[i] * (perm[i] - 1 - smallerDefined[perm[i]])) % MOD) +
(lessAmntLeft[perm[i]] * bin[i]) % MOD) % MOD;
}
}
int undef = totalUndef;
for (int i = 0; i < n; i++) {
if (perm[i] == 0) {
resultInpt[i] = (((((rowSum[i] * undef) % MOD) * (undef - 1)) % MOD) * INV_TWO) % MOD;
resultInpt[i] = (resultInpt[i] + (colSum[i] * totalSum) % MOD) % MOD;
undef--;
} else {
totalSum = (totalSum - greaterUndef[perm[i]] + MOD) % MOD;
}
}
int undefRight = undefinedAmnt[0];
int undefLeft = 0;
long rightFact = fact(undefRight);
long leftFact = 1;
resultInpt[0] = (resultInpt[0] * rightFact) % MOD;
for (int i = 1; i < n; i++) {
if (perm[i] == 0) {
rightFact = (rightFact * inverseElmnt(undefRight)) % MOD;
undefRight--;
}
if (perm[i - 1] == 0) {
undefLeft++;
leftFact = (leftFact * undefLeft) % MOD;
}
resultInpt[i] = (resultInpt[i] * ((rightFact * leftFact) % MOD)) % MOD;
}
long fact = 1;
int cnt = 1;
for (int i = n - 2; i >= 0; i--) {
resultInpt[i] = (resultInpt[i] * fact) % MOD;
cnt++;
fact = (fact * cnt) % MOD;
}
long result = fact(totalUndef);
for (int i = 0; i < n; i++) {
result = (result + resultInpt[i]) % MOD;
}
return result;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//BufferedReader br = new BufferedReader(new FileReader("D:\\cards44.txt"));
//BufferedReader br = new BufferedReader(new FileReader("D:\\cards41.txt"));
int n = Integer.parseInt(br.readLine());
int[] perm = new int[n];
StringTokenizer permTkn = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
perm[i] = Integer.parseInt(permTkn.nextToken());
}
//Date start = new Date();
long res = new CardsPermutationFinal().run(n, perm);
//Date end = new Date();
//System.out.println(end.getTime() - start.getTime() + "ms");
System.out.println(res);
}
private static void recalculateSize(Treap t) {
if (null != t) {
t.recalculateSize();
}
}
public Treap merge(Treap l, Treap r) {
if (null == l) {
return r;
}
if (null == r) {
return l;
}
Treap res;
if (l.y > r.y) {
Treap newTreap = merge(l.right, r);
recalculateSize(newTreap);
res = new Treap(l.x, l.y, l.left, newTreap);
} else {
Treap newTreap = merge(l, r.left);
recalculateSize(newTreap);
res = new Treap(r.x, r.y, newTreap, r.right);
}
recalculateSize(res);
return res;
}
private class Treap {
private int x;
private long y;
private Treap left;
private Treap right;
private int size;
public Treap(final int x, final long y, final Treap left, final Treap right) {
this.x = x;
this.y = y;
this.right = right;
this.left = left;
}
private void recalculateSize() {
size = (null == left ? 0 : left.size) + (null == right ? 0 : right.size) + 1;
}
public Treap[] split(int x) {
Treap newLeft = null;
Treap newRight = null;
if (x < this.x) {
if (this.left == null) {
newRight = new Treap(this.x, this.y, this.left, this.right);
} else {
Treap[] splitResult = this.left.split(x);
newLeft = splitResult[0];
newRight = new Treap(this.x, this.y, splitResult[1], this.right);
}
} else {
if (this.right == null) {
newLeft = new Treap(this.x, this.y, this.left, this.right);
} else {
Treap[] splitResult = this.right.split(x);
newLeft = new Treap(this.x, this.y, this.left, splitResult[0]);
newRight = splitResult[1];
}
}
CardsPermutationFinal.recalculateSize(newLeft);
CardsPermutationFinal.recalculateSize(newRight);
return new Treap[]{newLeft, newRight};
}
}
}
Cards Permutation JavaScript Solution
'use strict';
const fs = require('fs');
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let inputString = '';
let currentLine = 0;
const MAXN = BigInt(3e5 + 5),
mod = BigInt(1e9 + 7),
inv2 = (mod + 1n) >> 1n;
let c = [],
pre = [],
fac = [],
N = 0n,
count = 0n,
lex = 0n,
a, cur, ans, sum;
process.stdin.on('data', function(inputStdin) {
inputString += inputStdin;
});
process.stdin.on('end', function() {
inputString = inputString.split('\n');
main();
});
function readLine() {
return inputString[currentLine++];
}
function readLine() {
return inputString[currentLine++];
};
function add(a, b) {
a += b;
return a >= mod ? a - mod : a;
}
function pop(a, b) {
a -= b;
return a < 0n ? a + mod : a;
}
function mul(a, b) {
return (a * b) % mod;
}
function lowbit(i) {
return i & (-i)
}
function update (o, v) {
let i = o + 1n;
while (i <= N) {
c[i] += v;
i += lowbit(i)
}
}
function calc(o) {
let s = 0n, i = o + 1n;
while (i >= 1n) {
s += c[i]
i -= lowbit(i);
}
return s
}
function* range(start, end) {
for (let i = start; i < end; i++) {
yield i;
};
};
function cal2(n) {
return mul(mul(n, pop(n, 1n)), inv2)
}
function prepare() {
for (let i of range(1n, N + 1n)) {
a[i] -= 1n;
if (a[i] == -1n) count += 1n;
if (a[i] >= 0n) pre[a[i]] = 1n;
}
fac[0] = 1n;
for (let i of range(1n, N + 1n)) {
fac[i] = mul(i, fac[i - 1n])
}
for (let i of range(1n, N)) {
pre[i] += pre[i - 1n];
}
lex = mul(mul(N, pop(N, 1n)), inv2);
for (let i of range(1n, N + 1n)) {
if (a[i] != -1n) lex = pop(lex, a[i])
}
}
function solve(x) {
prepare()
cur = 0n
ans = 0n
for (let i of range(1n, N + 1n)) {
if (a[i] != -1n) {
sum = mul(fac[count], a[i] - calc(a[i]))
if (count >= 1n) {
sum = pop(sum, mul(fac[count - 1n], mul(cur, a[i] + 1n - pre[a[i]])))
}
sum = mul(sum, fac[N - i])
ans = add(ans, sum)
update(a[i], 1n)
lex = pop(lex, pop(N - 1n - a[i], pop(pre[N - 1n], pre[a[i]])))
} else {
sum = mul(lex, fac[count - 1n])
if (count >= 2n) {
sum = pop(sum, mul(fac[count - 2n], mul(cur, cal2(count))))
}
sum = mul(sum, fac[N - i])
ans = add(ans, sum)
cur += 1n
}
}
return add(ans, fac[count])
}
/*
* Complete the 'solve' function below.
*
* The function is expected to return a LONG_INTEGER.
* The function accepts INTEGER_ARRAY x as parameter.
*/
// function solve(x) {
// // Write your code here
// 1 1 2 3 4
// 2 1 2 4 3 = 1
// 3 1 3 2 4 = 2
// 4 1 3 4 2 = 3
// 5 1 4 2 3 = 4
// 6 1 4 3 2 = 5
// 7 2 1 3 4 1
// 8 2 1 4 3
// 9 2 3 1 4
// 10 2 3 4 1 2 +1 +1 = 1 0 0 =
// 11 2 4 1 3 2 +2 -3 = 1 1 -4 =
// 12 2 4 3 1
// 13 3 1 2 4 3!(3-1) + 0
// 14 3 1 4 2 3!(3-1) + 1
// 15 3 2 1 4
// 16 3 2 4 1
// 17 3 4 1 2
// 18 3 4 2 1
// 19 4 1 2 3 3!(4-1)
// 20 4 1 3 2
// 21 4 2 1 3 3!(4-1)
// 22 4 2 3 1
// 23 4 3 1 2
// 24 4 3 2 1 1 2 3 4
//
// }
// function main() {
// const ws = fs.createWriteStream(process.env.OUTPUT_PATH);
// const n = parseInt(readLine().trim(), 10);
// const a = readLine().replace(/\s+$/g, '').split(' ').map(aTemp => parseInt(aTemp, 10));
// const result = solve(a);
// ws.write(result + '\n');
// ws.end();
// }
function main() {
const ws = fs.createWriteStream(process.env.OUTPUT_PATH);
N = BigInt(parseInt(readLine().trim(), 10));
a = readLine().split(' ').map(aTemp => BigInt(parseInt(aTemp, 10, 64)));
let result;
a.unshift(0n)
for (let i=0; i < a.length; i++) {
pre.push(0n);
fac.push(0n);
c.push(0n);
};
result = solve(a);
ws.write(result + "\n");
ws.end();
};
Cards Permutation Python Solution
#!/bin/python3
import math
import os
import random
import re
import sys
from itertools import permutations
# fuckezd = [1]*3*(10**5)
# mddo = 10**9 + 7
# for i in range(1, len(fuckezd)):
# fuckezd[i] = (fuckezd[i-1] * i) % mddo
# def lex(l):
# count = 1
# for i in range(len(l)):
# remainingList = l[i:]
# remainingList.sort()
# index = remainingList.index(l[i])
# count += (fuckezd[len(l)-1-i]*index) % mddo
# return count % mddo
# # Complete the solve function below.
# def solve(x):
# if(x.count(0) == 0):
# return lex(x)
# set1 = set(range(1, len(x) + 1))
# y = x.copy()
# set2 = set(y)
# set3 = set1.difference(set2)
# missingNumbers = list(set3)
# zeroIndexList = [i for i, r in enumerate(x) if r == 0]
# count = 0
# for perm in permutations(missingNumbers):
# permListAdd = x.copy()
# for index in range(len(zeroIndexList)):
# permListAdd[zeroIndexList[index]] = perm[index]
# count += lex(permListAdd)
# return count % mddo
class fenwick:
def __init__(self, n):
self.tree = [0]*(n+1)
def update(self, i):
# i is 0 based index
i += 1
while i < len(self.tree):
self.tree[i] += 1
i += i & (-i)
def query(self, i):
# i is 0 based index
sum = 0
i += 1
while i > 0:
sum += self.tree[i]
i -= i & (-i)
return sum
def solve(x):
n = len(x)
mod = 1000000007
missing = [True]*n
bit1 = fenwick(n)
bit2 = fenwick(n)
for i in range(n):
x[i] -= 1
if x[i] != -1:
missing[x[i]] = False
missisng_elems = []
for i in range(n):
if missing[i]:
missisng_elems.append(i)
missing_sum = 0
m = len(missisng_elems)
for i in missisng_elems:
missing_sum += i
if i < n-1:
bit2.update(i+1)
fact = [1]*500010
for i in range(1, 500010):
fact[i] = i*fact[i-1] % mod
total_cost = 0
p = 0
y = 0
for i in range(n-1):
if x[i] != -1:
if m == 0:
D1 = bit1.query(x[i])
bit1.update(x[i]+1)
cost = (x[i] - D1)*fact[n-i-1]
else:
D1 = bit1.query(x[i])*m
no_of_smaller_missing_elems = bit2.query(x[i])
D2 = no_of_smaller_missing_elems*p
# print('D1:{} D2:{}'.format(D1, D2))
bit1.update(x[i]+1)
cost = (x[i]*m - (D1 + D2))*fact[m-1]*fact[n-i-1]
y += m - no_of_smaller_missing_elems
else:
if p == 0:
cost = (missing_sum - y)*fact[m-1]*fact[n-i-1]
else:
D1 = p*m*(m-1)//2
D2 = y*(m-1)
cost = (missing_sum * (m-1) - (D1 + D2))*fact[m-2]*fact[n-i-1]
p += 1
# print('i:{}, x[i]:{}, cost:{}'.format(i, x[i], cost))
total_cost += cost % mod
return (total_cost + fact[m]) % mod
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
n = int(input())
a = list(map(int, input().rstrip().split()))
result = solve(a)
fptr.write(str(result) + '\n')
fptr.close()