Il mio programma riesce a risolvere tutti quanti gli input proposti, ma nel sub task 4 da alcuni risultati errati a causa del timeout. Non riesco a pensare ad alcun modo per rendere il tutto più veloce.
#include <vector>
#include <cstdio>
using namespace std;
long long int greatest_common_divisor(long long int n1, long long int n2) {
if (n2==0) return n1;
return greatest_common_divisor(n2, n1 % n2);
}
long long int expMod(long long int x, long long int y, long long int p) { //Faccio la potenza con O(log(y))
long long int var = 1;
while (y>0) {
if (y%2==1) var=(var*x)%p; //Se è dispari moltiplica per X
y=y/2; //Divide l'esponente per 2
x=(x*x)%p; //Fa il quadrato dell'operazione corrente
} //while
var%=p; //Ritorna il modulo di var
return var;
}
vector<int> execute(int N, int K, int D, vector<int> A) {
//Creazione variabili
int holdPos;
const int mod=1e9+7;
vector<int> B(N, 1);
int startCount=N/greatest_common_divisor(N, D);//Quante volte torna alla posizione iniziale
int extra=K%startCount; //Trova quanti sono i movimenti dopo l'ultima posizione iniziale
for (int j=0; j<N; j++) { //Per ogni numero N
holdPos = j;
for (int i=0; i<startCount; i++) { //Per ogni ciclo
if (i < extra) B[j] = ((B[j]%mod) * (A[holdPos]%mod)) % mod; //Gestisce i valori extra
B[j] = ((B[j]%mod) * (expMod(A[holdPos], K/startCount, mod)%mod)) % mod;
holdPos = holdPos - D;
if (holdPos < 0) holdPos += N;
} //I (Per ogni ciclo)
} //J (N passaggi)
return B;
}
Ho provato a cercare in giro cosa potrebbe rendere la mia soluzione più efficacie, e l’unica cosa che sono riuscito a trovare (ma non capire tantomeno applicare) era quella di risolvere parte dei calcoli fuori dai cicli utilizzando un valore che è pari al modulo di tutti i valori all’interno dell’array.
Qualunque tipo di indizio o aiuto su come procedere è apprezzato.
Grazie in anticipo.
Ho provato a modificare il mio programma utilizzando un nuovo metodo, ma ancora non riesce a risolvere il problema e continua a dare TLE, qualche idea?
#include <vector>
#include <cstdio>
using namespace std;
long long int greatest_common_divisor(long long int n1, long long int n2) {
if (n2==0) return n1;
return greatest_common_divisor(n2, n1 % n2);
}
long long int expMod(long long int x, long long int y, long long int p) { //Faccio la potenza con O(log(y))
long long int var = 1;
while (y>0) {
if (y%2==1) var=(var*x)%p; //Se è dispari moltiplica per X
y=y/2; //Divide l'esponente per 2
x=(x*x)%p; //Fa il quadrato dell'operazione corrente
} //while
var%=p; //Ritorna il modulo di var
return var;
}
vector<int> execute(int N, int K, int D, vector<int> A) {
//Creazione variabili
int holdPos;
const int mod=1e9+7;
vector<int> B(N, 1);
int startCount=N/greatest_common_divisor(N, D);//Numero di cicli prima di tornare alla posizione iniziale
int cycles=K/startCount; //Numero di cicli completi
int extra=K%startCount; //Trova quanti sono i movimenti dopo l'ultima posizione iniziale
vector<long long int> cycleProd(N, 1);
vector<long long int> extraProd(N, 1);
for (int i=0; i<N; i++) { //Per ogni numero N
holdPos=i; //Tiene la posizione iniziale
for (int j=0; j<startCount; j++) {
if (j<extra) extraProd[i] = (extraProd[i] * A[holdPos]) % mod; //Calcola tutti i passaggi che non si ripetono
cycleProd[i] = (cycleProd[i] * A[holdPos]) %mod; //Calcola tutti i passaggi che si ripetono
holdPos=(holdPos-D+N)%N;
} //J (per ogni passaggio prima di tornare alla posizione iniziale)
cycleProd[i] = expMod(cycleProd[i], cycles, mod); //Fa l'esponente di tutti i passaggi che si ripetono in base a quante volte si ripetono
B[i] = ((cycleProd[i]) * (extraProd[i])) %mod; //Moltiplica i passaggi che si ripetono e quelli che non si ripetono
} //I (N passaggi)
return B;
}
Qualunque aiuto è apprezzato.
Grazie in anticipo.
Sono riuscito a trovare una soluzione che riesce a non fare timeout, ma non riesco a capire per quale ragione sbaglia alcuni risultati.
#include <vector>
using namespace std;
vector<int> execute(int N, int K, int D, vector<int> A) {
//Creazione variabili
const int mod=1e9+7;
vector<int> B(N, 1);
vector<int> copyA=A;
int newI = D;
//Inizializza B e gestisci le potenze di A dinamicamente
for (int i=0; K>0; i++, K>>=1) { //Per ogni ciclo, dimezzo K
if (K&1) for (int j=0; j<N; j++) B[j] = static_cast<long long>(B[j]) * copyA[j] % mod; //Calcolo il nuovo B se K e' dispari
//Aggiorna A per la prossima potenza di 2
vector<int> newA(N);
for (int j=0; j<N; j++) {
const int newIndex = (j-newI+N)%N; //Calcola l'indice con spostamento D verso destra
newA[j] = static_cast<long long>(copyA[j]) * copyA[newIndex] % mod; //Fa la moltiplicazione tra il nuovo e il vecchio A
} //J
copyA = newA; //Aggiorna A con la nuova potenza calcolata
newI = (2*newI)%N;
} //I
return B;
}
Questa soluzione utilizza l’esponenziazione binaria (exponentiation by squaring) per trovare i risultati con una complessità O(N*log(K)), e riesce a risolvere molti casi ma ne sbaglia alcuni e non riesco a capire la ragione.
Riesce a risolvere tutti i casi dove D=0, il che mi fa pensare che il problema si presenta a causa dello spostamento.
Se riesco a risolvere questo problema prima di aiuti esterni, scriverò nel prossimo post come ho fatto a risolverlo nella speranza che qualcuno che ne avrà bisogno in futuro lo vedrà.
Qualunque aiuto è apprezzato.
Grazie in anticipo.