Dana jest pamięć zawierająca
Napisać program zapisujący nową wartość zmiennej oraz odczytujący zmienną. Wartość zmiennej do zapisu będzie losowana z rozkładem jednostajnym. Jest to zadanie optymalizacyjne. Wynik punktowy będzie uzależniony od średniej liczby zapisów, które będziemy w stanie wykonać.
Dzielimy pamięć na
Średnio zapiszemy nieco poniżej
const int N=520; int t,B,M,c; char b[N],m[N]; void write() { int zero=1; REP(j,M) if (m[j] == '1') zero=0; if (!zero) { REP(i,B/M) { int free=1; REP(j,M) if (b[i*M+j] == '1') free=0; if (free) { REP(j,M) b[i*M+j] = m[j]; printf("1\n%s\n", b); fflush(stdout); return; } } } printf("0\n"); fflush(stdout); } void read() { REP(i,B/M) { int free=1; REP(j,M) if (b[i*M+j] == '1') free=0; if (free) break; REP(j,M) m[j] = b[i*M+j]; } printf("%s\n", m); fflush(stdout); } int main() { scanf("%d%d%d",&t,&B,&M); while (true) { int c; scanf("%d",&c); if (c == 0) break; if (t == 0) { scanf("%s%s",b,m); write(); } else { scanf("%s",b); read(); } } }
Innym pomysłem może być niezależne kodowanie bitów.
Dzielimy pamięć na
Zatem przy zapisie zliczamy parzystość jedynek w bloku i, jeśli jest inna
niż bit zmiennej, to dopisujemy kolejną jedynkę w bloku.
Ponieważ zdarzy się to z prawdopodobieństwem
Takie rozwiązanie dostaje około
void write() { REP(i,M) { int v=0; REP(j,B/M) if (b[i*B/M + j] == '1') v++; if (m[i]-'0' != (v & 1)) { if (v != B/M) { b[i*B/M + v] = '1'; } else { printf("0\n"); fflush(stdout); return; } } } printf("1\n%s\n", b); fflush(stdout); } void read() { REP(i,M) { int v=0; REP(j,B/M) if (b[i*B/M + j] == '1') v++; m[i] = '0' + (v & 1); } printf("%s\n", m); fflush(stdout); }
Idea będzie taka, żeby każdemu z
Oznaczmy przez
W celu zapisania nowej wartości, będziemy chcieli poszukać minimalnej liczby bitów,
które musimy zmienić na 1.
Wykorzystamy do tego programowanie dynamiczne.
Niech
Rekurencja jest prosta:
jeśli
Czas działania programowania dynamicznego wynosi
Takie rozwiązanie dostaje około
int v[N]; pair<int,int> dp[N][1<<K]; void write() { const int LEN = B/(M/K); REP(i,M/K) { int val = 0; REP(j,K) if (m[i*K + j] == '1') val |= 1<<j; REP(mask,1<<K) dp[0][mask] = make_pair(infty, -1); dp[0][0] = make_pair(0, -1); REP(j,LEN) REP(mask,1<<K) { if (b[i*LEN + j] == '1') { dp[j+1][mask] = make_pair(dp[j][mask ^ v[i*LEN + j]].first, 1); } else { dp[j+1][mask] = min( make_pair(dp[j][mask].first, 0), make_pair(1 + dp[j][mask ^ v[i*LEN + j]].first, 1)); } } int ans = dp[LEN][val].first; if (ans == infty) { printf("0\n"); fflush(stdout); return; } int j=LEN, mask=val; while (j) { if (dp[j][mask].second) { b[i*LEN + j-1] = '1'; mask ^= v[i*LEN + j-1]; } j--; } } printf("1\n%s\n", b); fflush(stdout); } void read() { const int LEN = B/(M/K); REP(i,M/K) { int val = 0; REP(j,LEN) if (b[i*LEN+j] == '1') { val ^= v[i*LEN+j]; } REP(j,K) m[i*K + j] = '0' + !!(val & (1<<j)); } printf("%s\n", m); fflush(stdout); } void init() { srand(0); REP(i,B) v[i] = rand() % (1<<K); }