Comentário por Frederico Bulhões
Cinco
Para resolvermos essa questão devemos observar uma coisa:
- O número inicial dado não é divisível por cinco
- Então para que haja resposta é necessário que a troca ocorra entre um número igual a 0 ou 5 e o número da ultima posição, pois então o novo número terminará em 0 ou 5, tornando-o divisível por cinc0.
Como
, podemos então fazer um algoritmo em
da seguinte forma:
Para todas as posições entre
e
checamos se o dígito daquela posição é 0 ou 5, caso seja, trocamos ele com o ultímo, e comparamos com a resposta computada até agora, caso maior ele se torna a resposta, e depois trocamos de volta o dígito atual com o ultímo.
Na implementação a seguir é ussado a função
do C++, que compara lexicográficamente dois vetores passados e retorna o maior.
Código para melhor entendimento:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <bits/stdc++.h> | |
| using namespace std; | |
| int main() | |
| { | |
| int n; | |
| cin >> n; | |
| vector<int> v(n), ans(n); | |
| for (int i = 0; i < n; i++) | |
| cin >> v[i]; | |
| bool ok = false; | |
| for (int i = 0; i < n; i++) { | |
| if (v[i] == 5 or v[i] == 0) { | |
| swap(v[i], v[n-1]); | |
| ans = max(ans, v); | |
| swap(v[i], v[n-1]); | |
| ok = true; | |
| } | |
| } | |
| if (!ok) | |
| cout << -1 << "\n"; | |
| else { | |
| for (int x : ans) | |
| cout << x << " "; | |
| cout << "\n"; | |
| } | |
| } |
Muro
Essa é uma questão de combinatória, em que podemos usar programação dinâmica como meio de resolver.
Vamos tentar achar uma recorrência para reolver o caso
:
Pelo desenho fornecido na questão pode-se ver que caso tenhamos um muro de tamanho
podemos preênche-lo da seguinte maneira:
- Colocando dois blocos de tamanho 1 próximos a um muro de tamanho

- Colocando dois blocos, um L e o outro um quadrado, de quatro formas diferentes, próximos a um muro de tamanho

- Colocado dois blocos L próximos de duas formas diferentes, próximos a um muro de tamanho

Então ficamos com a recorrência
. (Sempre tirando o módulo, como pedido na questão)
Os casos base são dados na questão,
= 1,
= 1,
.
Para computar
podemos usar programação dinâmica, de forma recursiva, salvando o resultado computado agora para não termos que computa-lo de novo, reduzindo a complexidade de
para
, ou podemos fazer de forma iterativa, fazendo um for de
até o
desejado, computado o valor atual usando a recorrência dada e os 3 valores anteriores.
Segue o código para melhor entandimento, (implementado de forma iterativa):
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <bits/stdc++.h> | |
| using namespace std; | |
| typedef long long ll; | |
| const ll mod = 1e9 + 7; | |
| const int maxn = 10101; | |
| ll dp[maxn]; | |
| int main() | |
| { | |
| int n; | |
| cin >> n; | |
| dp[0] = 1, dp[1] = 1, dp[2] = 5; | |
| for (int i = 3; i <= n; i++) { | |
| dp[i] = dp[i-1] + 4*dp[i-2] + 2*dp[i-3]; | |
| dp[i] %= mod; | |
| } | |
| cout << dp[n] << "\n"; | |
| } |
Baldes
Para resolvermos esse problema, devemos ter uma noção da estrutura Segment Tree, caso não a conheça recomendo que leia esse TUTORIAL para ter uma noção do que vamos falar agora.
Primeiro devemos perceber que para cada balde só importa o menor e o maior valor, e os outros são irrelevantes para a resposta, pois não faz sentido colocar uma bola com o outra de outro balde quando poderíamos pegar uma menor ou maior.
Nesse problema podemos em cada nó da Seg Tree, que representa os baldes entre
e
, guardar três valores:
- Valor máximo das bolas entre os baldes
e
, incluso. - Valor mínimo das bola entre os baldes
e
, incluso. - Máximo entre:
- Diferença máxima entre bolas de baldes entre
a
e de baldes entre
e
, (sendo
ponto do meio entre
e
); - Diferença máxima do filho da esquerda, bloco que representa
a 
- Diferênca máxima do filho da direita, bloco que representa
a 
- Diferença máxima entre bolas de baldes entre
Podemos então fazer as queries e updates de acordo com a questão, cada uma em
, somando u tempo total de 
Recomendo que leia a implementação com cuidado, e caso tenha dúvidas consulte um tutorial de Segment Tree
Código para melhor entendimento:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <bits/stdc++.h> | |
| using namespace std; | |
| struct Node | |
| { | |
| int mini, maxi, ans; | |
| }; | |
| Node join(Node const& a, Node const& b) | |
| { | |
| return {min(a.mini, b.mini), | |
| max(a.maxi, b.maxi), | |
| max({a.ans, b.ans, abs(a.maxi-b.mini), abs(b.maxi-a.mini)})}; | |
| } | |
| const int maxn = 101010; | |
| int v[maxn]; | |
| Node tree[maxn*4]; | |
| void build(int no, int l, int r) | |
| { | |
| if (l == r) { | |
| tree[no].mini = tree[no].maxi = v[l]; | |
| return; | |
| } | |
| int m = (l+r)/2; | |
| build(no*2+1, l, m); | |
| build(no*2+2, m+1, r); | |
| tree[no] = join(tree[no*2+1], tree[no*2+2]); | |
| } | |
| Node get(int no, int l, int r, int a, int b) | |
| { | |
| if (a <= l and r <= b) return tree[no]; | |
| int m = (l+r)/2; | |
| if (b <= m) return get(no*2+1, l, m, a, b); | |
| if (a > m) return get(no*2+2, m+1, r, a, b); | |
| return join(get(no*2+1, l, m, a, b), | |
| get(no*2+2, m+1, r, a, b)); | |
| } | |
| void upd(int no, int l, int r, int pos, int val) | |
| { | |
| if (l == r) { | |
| tree[no].mini = min(tree[no].mini, val); | |
| tree[no].maxi = max(tree[no].maxi, val); | |
| return; | |
| } | |
| int m = (l+r)/2; | |
| if (pos <= m) upd(no*2+1, l, m, pos, val); | |
| else upd(no*2+2, m+1, r, pos, val); | |
| } | |
| int main() | |
| { | |
| ios::sync_with_with_stdio(false), cin.tie(0); | |
| int n, q; | |
| cin >> n >> q; | |
| for (int i = 1; i <= n; i++) | |
| cin >> v[i]; | |
| build(0, 1, n); | |
| while (q–) { | |
| int op; | |
| cin >> op; | |
| if (op == 1) { | |
| int val, pos; | |
| cin >> val >> pos; | |
| upd(0, 1, n, pos, val); | |
| } | |
| else { | |
| int l, r; | |
| cin >> l >> r; | |
| cout << get(0, 1, n, l, r).ans << "\n"; | |
| } | |
| } | |
| } |
Mancha
Para resolver esse problema devemos fazer a seguinte observação:
- Caso
na mesma linha ou coluna que o
, é verdade que
para resolver esse problema, passando por cada linha e cada coluna checando essa condição em
.
Nessa implementação checamosse a soma de pontos que são da mancha entre o primeiro e ultimo daquela linha/coluna é igual a distância entre o primeiro e o último. Caso sim para toadas as linhas e colunas a resposta é sim. Senão a resposta é não.
Código para melhor entendimento:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> using namespace std; const int maxn = 1010; char m[maxn][maxn]; int main() { int n; cin >> n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> m[i][j]; for (int i = 0; i < n; i++) { int ini = n, fim, cnt = 0; for (int j = 0; j < n; j++) { if (m[i][j] == '*') { if (ini == n) { ini = j; } cnt++; fim = j; } } if (ini != n and cnt != fim-ini+1) { cout << "N\n"; return 0; } } for (int i = 0; i < n; i++) { int ini = n, fim, cnt = 0; for (int j = 0; j < n; j++) { if (m[j][i] == '*') { if (ini == n) { ini = j; } cnt++; fim = j; } } if (ini != n and cnt != fim-ini+1) { cout << "N\n"; return 0; } } cout << "S\n"; } Bolas
Para resolver esse problema podemos usar o Prinípio da Casa dos Pombos. Caso tenhamos um valor com mais de 4 ocorrências, então obrigatoriamente vamos ter que colocar uma dessas bola do lado da outra igual. Para resolver esse problema bastachecar essa condição, pois caso ela ocorra, só pode ocorrer com uma bola de um valor.
O código resultante tem complexidade de
.Código para melhor entendimento:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> using namespace std; int freq[10]; int main() { for (int i = 0; i < 8; i++) { int x; cin >> x; freq[x]++; } for (int i = 0; i <= 9; i++) { if (freq[i] > 4) { cout << "N\n"; return 0; } } cout << "S\n"; }

Comente