Ungleichheit bei der Umlagerung

10

Hintergrund

Die Umordnungsungleichung ist eine Ungleichung, die auf der Neuanordnung von Zahlen basiert. Wenn ich zwei Listen von Zahlen gleicher Länge habe, x 0 , x 1 , x 2 ... x n-1 und y 0 , y 1 , y 2 ... y n-1 gleicher Länge, wobei I. Ich darf die Zahlen in der Liste neu anordnen. Eine Möglichkeit, die Summe x 0 y 0 + x 1 y 1 + x 2 y 2 + ... + x n-1 y n-1 zu maximieren, besteht darin, die 2 Listen zu sortieren nicht abnehmende Reihenfolge.

Lesen Sie hier den Wikipedia- Artikel.

Aufgabe

Sie würden ein Programm schreiben, das Eingaben von STDIN entgegennimmt, oder eine Funktion, die 2 Arrays (oder verwandte Container) von Zahlen (die gleich lang sind) akzeptiert.

Angenommen, Sie schreiben eine Funktion, die zwei Arrays (a und b) akzeptiert, werden Sie die Anzahl der Möglichkeiten finden, wie Sie die Zahlen im zweiten Array (b) neu anordnen können, um Folgendes zu maximieren:

a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+...+a[n-1]*b[n-1]

In diesem Fall, wenn das Array b [1 0 , 2 1 , 2 2 , 3 3 , 3 4 ] ist (Indizes zur Klarheit),

[1 0 , 2 1 , 2 2 , 3 3 , 3 4 ],

[1 0 , 2 1 , 2 2 , 3 4 , 3 3 ] (tauschen Sie die beiden 3er aus)

[1 0 , 2 2 , 2 1 , 3 3 , 3 4 ] (tauschen Sie die beiden 2er aus)

[1 0 , 2 2 , 2 1 , 3 4 , 3 3 ] (Tauschen Sie die beiden 3er und die beiden 2er)

gelten als unterschiedliche Regelungen. Das ursprüngliche Array selbst zählt ebenfalls als mögliche Umlagerung, wenn es auch die Summe maximiert.

Bei der STDIN-Eingabe können Sie davon ausgehen, dass die Länge der Arrays vor den Arrays angegeben wird (bitte geben Sie an, dass Sie sie verwenden), oder dass die Arrays in verschiedenen Zeilen bereitgestellt werden (bitte auch angeben).

Hier sind die 4 möglichen Eingaben (der Einfachheit halber):

5 1 1 2 2 2 1 2 2 3 3 (length before arrays)

1 1 2 2 2 1 2 2 3 3 (the 2 arrays, concatenated)

1 1 2 2 2
1 2 2 3 3 (the 2 arrays on different lines)

5
1 1 2 2 2
1 2 2 3 3 (length before arrays and the 2 arrays on different lines)

Für die Ausgabe können Sie die Antwort zurückgeben (wenn Sie eine Funktion schreiben) oder die Antwort an STDOUT drucken. Sie können den Antwort-Mod 10 9 +7 (von 0 bis 10 9 + 6 ) ausgeben, wenn dies bequemer ist.

Testfälle (und Erklärung):

[1 1 2 2 2] [1 2 2 3 3] => 24

Die ersten 2 Einträge müssen 1 und 2 sein. Die letzten 3 Einträge sind 2, 3 und 3. Es gibt zwei Möglichkeiten, die 2 zwischen den ersten 2 Einträgen und den letzten 2 Einträgen anzuordnen. Unter den ersten beiden Einträgen gibt es zwei Möglichkeiten, sie neu anzuordnen. Unter den letzten beiden Einträgen gibt es 6 Möglichkeiten, sie neu anzuordnen.

[1 2 3 4 5] [6 7 8 9 10] => 1

Es gibt nur einen Weg, nämlich die in den Arrays angegebene Anordnung.

[1 1 ... 1 1] [1 1 ... 1 1] (10000 numbers) => 10000! or 531950728

Jede mögliche Permutation des zweiten Arrays ist gültig.

Dennis 'Testfall: Pastebin => 583159312 (mod 1000000007)

Wertung:

Dies ist Code-Golf, also gewinnt die kürzeste Antwort.

Im Falle eines Unentschieden werden die Unentschieden zum Zeitpunkt der Einreichung unterbrochen, was die frühere Einreichung begünstigt.

Beachten:

Die Container sind möglicherweise unsortiert.

Die ganzen Zahlen in den Containern können Null oder negativ sein.

Das Programm muss schnell genug (höchstens eine Stunde) für Arrays mit bescheidener Größe (ca. 10000 Länge) ausgeführt werden.

Inspiriert von dieser Frage zu Mathematics Stack Exchange.

Element118
quelle
2
Bitte stellen Sie einen Testfall mit 10000 Elementen pro Array bereit, damit wir überprüfen können, ob unser Code korrekt funktioniert und schnell genug ist.
Dennis
1
In dem Beispiel, das Sie für den Austausch des zweiten Arrays geben [1_0, 2_2, 2_1, 3_4, 3_3] (tauschen Sie die beiden 2er und tauschen Sie die beiden 3er aus), fehlt
Willem
Akzeptieren Sie Eingaben wie [. . .]PLZ antworten
Abr001am
Wenn wir eine Funktion einreichen, müssen wir zwei separate Argumente verwenden oder können wir ein Array von Arrays verwenden?
Dennis
Nun, Array von Arrays scheint in Ordnung zu sein und beeinflusst die Herausforderung nicht zu sehr. Ich werde am Testfall arbeiten.
Element118

Antworten:

4

CJam, 30 26 Bytes

q~](/:$_za+{e`0f=:m!:*}//*

Probieren Sie es online im CJam-Interpreter aus .

Es vervollständigt diesen Testfall in weniger als einer Sekunde:

$ time cjam <(echo 'q~](/:$_za+{e`0f=:m!:*}%)\:*\/N') < test-large.in | md5sum
5801bbf8ed0f4e43284f7ec2206fd3ff  -

real    0m0.308s
user    0m0.667s
sys     0m0.044s

Das Ausführen im Online-Interpreter sollte weniger als 10 Sekunden dauern.

Algorithmus

Das Ergebnis hängt nicht von der Reihenfolge von A ab , daher können wir davon ausgehen, dass es sortiert ist. Dies bedeutet, dass B auch sortiert werden muss, um das maximale Punktprodukt zu erreichen.

Wenn nun r 1 ,… r n die Länge der Läufe des sortierten A sind , gibt es ∏r k ! verschiedene Umlagerungen der Elemente von A , die immer noch zu aufsteigender Reihenfolge führen.

Wenn s 1 ,… s n die Länge der Läufe des sortierten B sind , gibt es ebenfalls ∏s k ! verschiedene Umlagerungen der Elemente von B , die immer noch zu aufsteigender Reihenfolge führen.

Dies zählt jedoch alle Paarungen mehrmals. Wenn wir die Paare der entsprechenden Elemente von sortiertem A und sortiertem B nehmen und t 1 definieren ,… t n als die Länge der Läufe des resultierenden Arrays, ∏t k ! ist der oben genannte Multiplikator.

Somit ist das gewünschte Ergebnis (∏r k !) × (∏s k !) ÷ (∏t k !) .

Code

 q~                          Read and evaluate all input.
   ]                         Wrap the resulting integers in an array.
    (                        Shift out the first (length).
     /                       Split the remainder into chunks of that length.
      :$                     Sort each chunk.
        _z                   Push a copy and transpose rows with columns.
                             This pushes the array of corresponding pairs.
          a+                 Wrap in array and concatenate (append).
            {          }/    For A, B, and zip(A,B):
             e`                Perform run-length encoding.
               0f=             Select the runs.
                  :m!          Apply factorial to each.
                     :*        Reduce by multiplication.
                         /   Divide the second result by the third.
                          *  Multiply the quotient with the first result.
Dennis
quelle
6

Pyth, 29 28 Bytes

M/*FPJm*F.!MhMrd8aFCB,SGSHeJ

Probieren Sie es online im Pyth Compiler aus .

Algorithmus

Das Ergebnis hängt nicht von der Reihenfolge von A ab , daher können wir davon ausgehen, dass es sortiert ist. Dies bedeutet, dass B auch sortiert werden muss, um das maximale Punktprodukt zu erreichen.

Wenn nun r 1 ,… r n die Länge der Läufe des sortierten A sind , gibt es ∏r k ! verschiedene Umlagerungen der Elemente von A , die immer noch zu aufsteigender Reihenfolge führen.

Wenn s 1 ,… s n die Länge der Läufe des sortierten B sind , gibt es ebenfalls ∏s k ! verschiedene Umlagerungen der Elemente von B , die immer noch zu aufsteigender Reihenfolge führen.

Dies zählt jedoch alle Paarungen mehrmals. Wenn wir die Paare der entsprechenden Elemente von sortiertem A und sortiertem B nehmen und t 1 definieren ,… t n als die Länge der Läufe des resultierenden Arrays, ∏t k ! ist der oben genannte Multiplikator.

Somit ist das gewünschte Ergebnis (∏r k !) × (∏s k !) ÷ (∏t k !) .

Code

M/*FPJm*F.!MhMrd8aFCB,SGSHeJ

M                             Define g(G,H):
                      SGSH      Sort G and H.
                     ,          For the pair of the results.
                   CB           Bifurcated zip (C).
                                This returns [[SG, SH], zip([SG, SH])].
                 aF             Reduce by appending.
                                This returns [SG, SH, zip([SG, SH])].
      m                         Map; for each d in the resulting array:
              rd8                 Perform run-length encoding on d.
            hM                    Mapped "head". This returns the lengths.
         .!M                      Mapped factorial.
       *F                         Reduce by multiplication.
     J                          Save the result in J.
    P                           Discard the last element.
  *F                            Reduce by multiplication.
 /                  
                          eJ    Divide the product by the last element of J.
                                Return the result of the division.

Nachprüfung

Ich habe pseudozufällig 100 Testfälle der Länge 6 generiert, die ich mit dem obigen Code und diesem Brute-Force-Ansatz gelöst habe:

Ml.Ms*VGZ.pH

M             Define g(G,H) (or n(G,H) on second use):
         .pH    Compute all permutations of H.
  .M            Filter .pH on the maximal value of the following;
                 for each Z in .pH:
     *VGZ         Compute the vectorized product of G and Z.
    s             Add the products.
                  This computes the dot product of G and Z.
 l              Return the length of the resulting array.

Dies waren die Ergebnisse:

$ cat test.in
6,9,4,6,8,4,5,6,5,0,8,2
0,7,7,6,1,6,1,7,3,3,8,0
3,6,0,0,6,3,8,2,8,3,1,1
2,3,0,4,0,6,3,4,5,8,2,4
9,1,1,2,2,8,8,1,7,4,9,8
8,3,1,1,9,0,2,8,3,4,9,5
2,0,0,7,7,8,9,2,0,6,7,7
0,7,4,2,2,8,6,5,0,5,4,9
2,7,7,5,5,6,8,8,0,5,6,3
1,7,2,7,7,9,9,2,9,2,9,8
7,2,8,9,9,0,7,4,6,2,5,3
0,1,9,2,9,2,9,5,7,4,5,6
8,4,2,8,8,8,9,2,5,4,6,7
5,2,8,1,9,7,4,4,3,3,0,0
9,3,6,2,5,5,2,4,6,8,9,3
4,2,0,6,2,3,5,3,6,3,1,4
4,8,5,2,5,0,5,1,2,5,9,5
6,8,4,4,9,5,9,5,4,2,8,7
8,9,8,1,2,2,9,0,5,6,4,9
4,7,6,8,0,3,7,7,3,9,8,6
7,5,5,6,3,9,3,8,8,4,8,0
3,8,1,8,5,6,6,7,2,8,5,3
0,9,8,0,8,3,0,3,5,9,5,6
4,2,7,7,5,8,4,2,6,4,9,4
3,5,0,8,2,5,8,7,3,4,5,5
7,7,7,0,8,0,9,8,1,4,8,6
3,9,7,7,4,9,2,5,9,7,9,4
4,5,5,5,0,7,3,4,0,1,8,2
7,4,4,2,5,1,7,4,7,1,9,1
0,6,2,5,4,5,1,8,0,8,9,9
3,8,5,3,2,1,1,2,2,2,8,4
6,1,9,1,8,7,5,6,9,2,8,8
6,2,6,6,6,0,2,7,8,6,8,2
0,7,1,4,5,5,3,4,4,0,0,2
6,0,1,5,5,4,8,5,5,2,1,6
2,6,3,0,7,4,3,6,0,5,4,9
1,4,8,0,5,1,3,2,9,2,6,5
2,7,9,9,5,0,1,5,6,8,4,6
4,0,1,3,4,3,6,9,1,2,7,1
6,5,4,7,8,8,6,2,3,4,1,2
0,3,6,3,4,0,1,4,5,5,5,7
5,4,7,0,1,3,3,0,2,1,0,8
8,6,6,1,6,6,2,2,8,3,2,2
7,1,3,9,7,4,6,6,3,1,5,8
4,8,3,3,9,1,3,4,1,3,0,6
1,4,0,7,4,9,8,4,2,1,0,3
0,4,1,6,4,4,4,7,5,1,4,2
0,0,4,4,9,6,7,2,7,7,5,4
9,0,5,5,0,8,8,9,5,9,5,5
5,7,0,4,2,7,6,1,1,1,9,1
3,1,7,5,0,3,1,4,0,9,0,3
4,4,5,7,9,5,0,3,7,4,7,5
7,9,7,3,0,8,4,0,0,3,1,0
2,4,4,3,1,2,5,2,9,0,8,5
4,8,7,3,0,0,9,3,7,3,0,6
8,9,1,0,7,7,6,0,3,1,8,9
8,3,1,7,3,3,6,1,1,7,6,5
6,5,6,3,3,0,0,5,5,0,6,7
2,4,3,9,7,6,7,6,5,6,2,0
4,8,5,1,8,4,4,3,4,5,2,5
7,5,0,4,6,9,5,0,5,7,5,5
4,8,9,5,5,2,3,1,9,7,7,4
1,5,3,0,3,7,3,8,5,5,3,3
7,7,2,6,1,6,6,1,3,5,4,9
9,7,6,0,1,4,0,4,4,1,4,0
3,5,1,4,4,0,7,1,8,9,9,1
1,9,8,7,4,9,5,2,2,1,2,9
8,1,2,2,7,7,6,8,2,3,9,7
3,5,2,1,3,5,2,2,4,7,0,7
9,6,8,8,3,5,2,9,8,7,4,7
8,8,4,5,5,1,5,6,5,1,3,3
2,6,3,5,0,5,0,3,4,4,0,5
2,2,7,6,3,7,1,4,0,3,8,3
4,8,4,2,6,8,5,6,2,5,0,1
7,2,4,3,8,4,4,6,5,3,9,4
4,6,1,0,6,0,2,6,7,4,9,5
6,3,3,4,6,1,0,8,6,1,7,5
8,3,4,2,8,3,0,1,8,9,1,5
9,6,1,9,1,1,8,8,8,9,1,4
3,6,1,6,1,4,5,1,0,1,9,1
6,4,3,9,3,0,5,0,5,3,2,4
5,2,4,6,1,2,6,0,1,8,4,0
3,5,7,6,3,6,4,5,2,8,1,5
6,3,6,8,4,2,7,1,5,3,0,6
9,1,5,9,9,1,1,4,5,7,3,0
1,6,7,3,5,8,6,5,5,2,6,0
2,8,8,6,5,5,2,3,8,1,9,8
0,4,5,3,7,6,2,5,4,3,2,5
5,1,2,3,0,3,4,9,4,9,4,9
5,8,2,2,0,2,4,1,1,7,0,3
0,6,0,0,3,6,3,6,2,2,2,9
2,4,8,1,9,4,0,8,8,0,4,7
3,9,1,0,5,6,8,8,2,5,2,6
5,3,8,9,1,6,5,9,7,7,6,1
8,6,9,6,1,1,6,7,7,3,2,2
7,2,1,9,8,8,5,3,6,3,3,6
9,9,4,8,7,9,8,6,6,0,3,1
8,3,0,9,1,7,4,8,0,1,6,2
8,2,6,2,4,0,2,8,9,6,3,7
1,0,8,5,3,2,3,7,1,7,8,2
$ while read; do
> pyth -c 'M/*FPJm*F.!MhMrd8aFCB,SGSHeJMl.Ms*VGZ.pHAc2Q,gGHnGH' <<< "$REPLY"
> done < test.in
[4, 4]
[4, 4]
[8, 8]
[4, 4]
[8, 8]
[2, 2]
[4, 4]
[4, 4]
[4, 4]
[36, 36]
[2, 2]
[8, 8]
[24, 24]
[8, 8]
[2, 2]
[2, 2]
[6, 6]
[2, 2]
[8, 8]
[2, 2]
[12, 12]
[2, 2]
[8, 8]
[12, 12]
[4, 4]
[12, 12]
[4, 4]
[6, 6]
[8, 8]
[8, 8]
[6, 6]
[4, 4]
[48, 48]
[8, 8]
[4, 4]
[1, 1]
[4, 4]
[4, 4]
[8, 8]
[4, 4]
[12, 12]
[2, 2]
[96, 96]
[2, 2]
[4, 4]
[2, 2]
[6, 6]
[24, 24]
[24, 24]
[48, 48]
[4, 4]
[8, 8]
[12, 12]
[8, 8]
[4, 4]
[2, 2]
[24, 24]
[16, 16]
[2, 2]
[8, 8]
[24, 24]
[4, 4]
[24, 24]
[4, 4]
[12, 12]
[8, 8]
[12, 12]
[4, 4]
[8, 8]
[4, 4]
[16, 16]
[4, 4]
[8, 8]
[8, 8]
[4, 4]
[4, 4]
[4, 4]
[4, 4]
[72, 72]
[24, 24]
[4, 4]
[4, 4]
[4, 4]
[2, 2]
[12, 12]
[4, 4]
[8, 8]
[4, 4]
[36, 36]
[6, 6]
[12, 12]
[8, 8]
[4, 4]
[2, 2]
[8, 8]
[24, 24]
[6, 6]
[1, 1]
[2, 2]
[2, 2]

Um zu überprüfen, ob meine Einreichung die Geschwindigkeitsanforderungen erfüllt, habe ich sie mit diesem Testfall ausgeführt .

$ time pyth -c 'M/*FPJm*F.!MhMrd8aFCB,SGSHeJAc2QgGH' < test-large.in | md5sum
5801bbf8ed0f4e43284f7ec2206fd3ff  -

real    0m0.233s
user    0m0.215s
sys     0m0.019s
Dennis
quelle
2

Matlab, 230 Bytes

Bearbeiten: Viele Dinge wurden behoben, um den Testfällen von Dennis zu entsprechen, und nnz wird aufgrund von Nullwerten durch numel ersetzt.

f=1;t=-1;q=1;a=sort(input(''));b=sort(input(''));for i=unique(a)c=b(find(a==i));r=numel(c(c==t));f=f*factorial(numel(c))*sum(arrayfun(@(u)nchoosek(max(q,r),u),0:min(q,r)));z=c(end);y=numel(c(c==z));q=(t==z)*(q+r)+(t~=z)*y;t=z;end,f

Ausführung

[2 2 1 2 1]
[3 2 3 2 1]

f =

    24

Dennis 'Testfall:

   A = importdata('f:\a.csv'); for i=1:100,a=sort(A(i,1:6));b=sort(A(i,7:12));
   f=1;t=-1;q=1;for i=unique(a)c=b(find(a==i));r=numel(c(c==t));f=f*factorial(numel(c))*sum(arrayfun(@(u)nchoosek(max(q,r),u),0:min(q,r)));z=c(end);y=numel(c(c==z));q=(t==z)*(q+r)+(t~=z)*y;t=z;end;
   disp(f);end

Ausgänge:

 4

 4

 8

 4

 8

 2

 4

 4

 4

36

 2

 8

24

 8

 2

 2

 6

 2

 8

 2

12

 2

 8

12

 4

12

 4

 6

 8

 8

 6

 4

48

 8

 4

 1

 4

 4

 8

 4

12

 2

96

 2

 4

 2

 6

24

24

48

 4

 8

12

 8

 4

 2

24

16

 2

 8

24

 4

24

 4

12

 8

12

 4

 8

 4

16

 4

 8

 8

 4

 4

 4

 4

72

24

 4

 4

 4

 2

12

 4

 8

 4

36

 6

12

 8

 4

 2

 8

24

 6

 1

 2

 2
Abr001am
quelle
Nun, es löst das Problem, daher sollte die Eingabe nicht zu wichtig sein.
Element118
1

C ++, 503 Bytes

(nur zum Spaß, eine Sprache ohne Golf)

#import<iostream>
#import<algorithm>
#define U 12345
#define l long long
using namespace std;int N,X=1,Y=1,Z=1,x[U],y[U],i=1;l p=1,M=1000000007,f[U];l e(l x,int y){return y?y%2?(x*e(x,y-1))%M:e((x*x)%M,y/2):1;}main(){for(f[0]=1;i<U;i++)f[i]=(f[i-1]*i)%M;cin>>N;for(i=0;i<N;i++)cin>>x[i];for(i=0;i<N;i++)cin>>y[i];sort(x,x+N);sort(y,y+N);for(i=1;i<N;i++)x[i]^x[i-1]?p=p*f[X]%M,X=1:X++,y[i]^y[i-1]?p=p*f[Y]%M,Y=1:Y++,x[i]^x[i-1]|y[i]^y[i-1]?p=p*e(f[Z],M-2)%M,Z=1:Z++;cout<<p*f[X]%M*f[Y]%M*e(f[Z],M-2)%M;}

Ungolfed Version:

#include <cstdio>
#include <algorithm>
#define MOD 1000000007
using namespace std;
int N; // number of integers
int x[1000010]; // the 2 arrays of integers
int y[1000010];
long long product = 1;
long long factorial[1000010]; // storing factorials mod 1000000007
long long factorialInv[1000010]; // storing the inverse mod 1000000007
long long pow(long long x, int y) {
    if (y == 0) return 1;
    if (y == 1) return x;
    if (y%2 == 1) return (x*pow(x, y-1))%MOD;
    return pow((x*x)%MOD, y/2);
}
int main(void) {
    //freopen("in.txt", "r", stdin); // used for faster testing
    //precomputation
    factorial[0] = factorial[1] = 1;
    for (int i=2;i<=1000000;i++) {
        factorial[i] = (factorial[i-1]*i)%MOD;
        factorialInv[i] = pow(factorial[i], MOD-2);
    }
    // input
    scanf("%d", &N);
    for (int i=0;i<N;i++) {
        scanf("%d", &x[i]);
    }
    for (int i=0;i<N;i++) {
        scanf("%d", &y[i]);
    }
    // sort the 2 arrays
    sort(x, x+N);
    sort(y, y+N);
    int sameX = 1;
    int sameY = 1;
    int sameXY = 1;
    for (int i=1;i<N;i++) {
        if (x[i]==x[i-1]) {
            sameX++;
        } else {
            product *= factorial[sameX];
            product %= MOD;
            sameX = 1;
        }
        if (y[i]==y[i-1]) {
            sameY++;
        } else {
            product *= factorial[sameY];
            product %= MOD;
            sameY = 1;
        }
        if (x[i]==x[i-1] && y[i]==y[i-1]) {
            sameXY++;
        } else {
            product *= factorialInv[sameXY];
            product %= MOD;
            sameXY = 1;
        }
    }
    product *= factorial[sameX];
    product %= MOD;
    product *= factorial[sameY];
    product %= MOD;
    product *= factorialInv[sameXY];
    product %= MOD;
    printf("%lld\n", product);
    return 0;
}
Element118
quelle