HZNUOJ 2803 prefixo bidimensional e + gcd

Sharpshooter JoneySun (versão fácil)

Limite de tempo: 1 s Limite de memória: 256 MB
Envio : 146 AC : 32 Pontuação : 100,00

Descrição A
versão fácil e a versão um pouco difícil diferem apenas no intervalo de dados

JoneySun estava preso em uma prisão dividida por uma grade 1 × 1 pela esposa do mal. A esposa do mal assistia às piadas de JoneySun em algum lugar da prisão. Felizmente, JoneySun tinha uma arma na mão. Infelizmente, é a esposa que domina a técnica do doppelganger.

Achamos que esta prisão é uma grade de 2n × 2m. JoneySun está preso no meio. Com exceção de JoneySun, há um avatar wifepie nas outras interseções da grade. O alcance da arma de JoneySun é infinito. Se a bala atingir o clone, o clone desaparecerá e a bala continuará a se mover em linha reta. Se a bala atingir o corpo da esposa, ela será destruída por JoneySun. JoneySun queria saber o número máximo de balas necessárias para destruir uma esposa.


Um inteiro T na primeira linha da entrada (1≤T≤100) indica que existem T grupos de entradas

Dois inteiros n, m (1≤n, m≤103) na segunda linha, veja o título para o significado

Amostras
entrada
1
1 1
saída
8
Dica

Conforme mostrado na figura, o ponto vermelho indica a localização do JoneySun e o ponto azul indica o clone do wifepie. São necessários até 8 balas para destruir todos os clones do wifipie.

Por favor, preste atenção à complexidade, T é muito grande, por favor, tente todas as otimizações metafísicas que você pode pensar

Solução do problema: O significado do problema é descobrir quantos raios não sobrepostos do ponto de origem a cada vértice, ou seja, descobrir se mdc (i, j) é igual a 1, ou mdc (i, j) = d, mdc Se (i / d, j / d) é igual a 1, se for igual a 1, significa que é um lado viável. Como todo retângulo é simétrico, ele pode ser transformado em um problema de quadrante para resolver. Como o problema tem 100 conjuntos de dados de teste, a complexidade é relativamente grande, então a solução violenta será T, então consideramos usar um prefixo bidimensional e pré-processamento, e então O (1) para consulta.
O código AC é o seguinte:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 10000007
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 1e6 + 50;
const int N = 35;
const int INF = 0x3f3f3f3f;
const int inf = 0xfffffff;//比INF小,防止累加爆int
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
int gcd(int x, int y) {
    
    
	return y ? gcd(y, x % y) : x;
}
int n, m;
int dp[1020][1020];
int main() {
    
    
	mem(dp, 0);
	for (int i = 1; i <= 1010; ++i) {
    
    
		for (int j = 1; j <= 1010; ++j) {
    
    
			int step = gcd(i, j);
			if (step == 1)dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + step;//如果是可行边,则加上改点的值
			else {
    
    
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];//如果不是可行边,则不加
			}
		}
	}
	int t;
	scanf("%d", &t);
	while (t--) {
    
    
		scanf("%d%d", &n, &m);
		int ans = dp[n][m] * 4 + 4;
		printf("%d\n", ans);
	}
	return 0;
}

Acho que você gosta

Origin blog.csdn.net/qq_40924271/article/details/107872288
Recomendado
Clasificación