1. Link do título:
UVA-11916
2. A ideia principal do tópico:
Há um problema, há uma área retangular de tamanho m * n, onde b pontos estão bloqueados e agora há k cores.
É necessário preencher os pontos não bloqueados.Cada grade só pode ser preenchida com uma cor, e duas grades adjacentes na mesma coluna não podem ter a mesma cor.
Registre o número de esquemas de cores como r (mod p) e produza r.
Agora o problema está invertido: dados n, b, k, re as coordenadas do ponto de bloqueio, encontre o menor m.
3. Análise:
Obviamente m> = max (x [i]).
Portanto, primeiro encontre o número de esquemas de cores de 1 ~ max (x (i)).
Para a rede não bloqueante na primeira linha, seu número de esquemas de cores é k.
Para a rede não bloqueadora nas linhas 2 ~ m, se for uma rede bloqueadora, o número de esquemas de cores é k, caso contrário, é k-1.
Desta forma, o número de esquemas de cores para as linhas 1 ~ max (x [i]) pode ser calculado.Se for igual a r, a resposta é max (x [i]).
Caso contrário, calcule a coloração de 1 ~ max (x [i]) + 1 linha da mesma maneira (porque a grade de bloqueio de max (x [i]) afetará o número de coloração de max (x [i]) + 1 linha) Número de planos
Se for igual a r, a resposta é max (x [i]) + 1.
Caso contrário, defina o número de esquemas de cores de 1 ~ max (x [i]) + 1 linha como cnt, e adicione x linhas com base em max (x [i]) + 1 linha
Acessível:
Organize-se para obter:
Aqui você pode felizmente colocar o modelo!
PS: n, m ≤ 1e8, ao fazer a pergunta considera-se nm ≤ 1e8, T é uma noite ...
4. Implementação do código:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (int)5e2;
const int mod = (int)1e8 + 7;
int m, n, k, b, r;
int x[M + 5], y[M + 5];
set < pair<int, int> > block;
ll quick(ll a, ll b)
{
ll sum = 1;
while(b)
{
if(b & 1) sum = sum * a % mod;
a = a * a % mod;
b >>= 1;
}
return sum;
}
ll inv(ll n)
{
return quick(n, mod - 2);
}
int cal()
{
int c = 0;
for(int i = 1; i <= b; ++i)
{
if(x[i] < m && !block.count(make_pair(x[i] + 1, y[i])))
++c;
}
c += n;
for(int i = 1; i <= b; ++i)
{
if(x[i] == 1)
--c;
}
return quick(k, c) * quick(k - 1, 1ll * n * m - b - c) % mod;
}
int BSGS(int a, int b)
{
map <int, int> Hash;
int t = (int)sqrt(mod) + 1;
for(int j = 0; j < t; ++j)
{
int val = quick(a, j) * b % mod;
Hash[val] = j;
}
a = quick(a, t);
if(a == 0) return b == 0 ? 1 : -1;
for(int i = 0; i <= t; ++i)
{
int val = quick(a, i);
int j = (Hash.find(val) == Hash.end() ? -1 : Hash[val]);
if(j >= 0 && i * t - j >= 0) return i * t - j;
}
return -1;
}
int work()
{
int cnt = cal();
if(cnt == r)
return m;
int c = 0;
for(int i = 1; i <= b; ++i)
{
if(x[i] == m)
++c;
}
++m;
cnt = cnt * quick(k, c) % mod * quick(k - 1, n - c) % mod;
if(cnt == r)
return m;
return BSGS(quick(k - 1, n), r * inv(cnt) % mod) + m;
}
int main()
{
int T;
scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
m = 1;
block.clear();
scanf("%d %d %d %d", &n, &k, &b, &r);
for(int i = 1; i <= b; ++i)
{
scanf("%d %d", &x[i], &y[i]);
m = max(m, x[i]);
block.emplace(make_pair(x[i], y[i]));
}
printf("Case %d: %d\n", ca, work());
}
return 0;
}