T-Primes, RSA Attack, DDF
Autor(es):
n (1 ≤ n ≤ 10^5 )
xi (1 ≤ xi ≤ 10^12 )
1 < (algum_numero_primo) < x
Para x = 9,
1 < 3 < 9
if (n == 1) cout << “NO”;
else if (quadrado_perfeito(n) && ehPrimo[sqrt(n)])
cout << “YES”;
else
cout << “NO”;
vector<bool> ehPrimo;
ll MAXN = 1000000;
void crivo()
{
ehPrimo = vector<bool>(MAXN + 1, true);
ehPrimo[0] = ehPrimo[1] = false;
for (ll i = 2; i * i <= MAXN; i++)
{
if (!ehPrimo[i])continue;
for (ll m = i * i; m <= MAXN; m += i)
ehPrimo[m] = false;
}
}
O enunciado nos apresenta o seguinte problema
1ª ETAPA: manipular a equação
me (mod n) = c (mod n)
elevar ambos os lados da equação por x
(me)x (mod n) = (c)x (mod n)
mex (mod n) = cx (mod n)
Podemos, então, supor que ex = 1, pois, assim, mex = m1.
Assim, temos: m (mod n) = cx (mod n)
Agora, sabemos que o valor de m é o resultado da potência cx.
Contudo, não sabemos o valor de x, portanto precisamos encontrá-lo.
2ª ETAPA: encontrar o valor de x
Podemos perceber, pelas afirmações 1 e 2, que:
ex = gcd(e, (p - 1)(q - 1)) = 1
ax + by = c
Euclides equações diofantinas com a seguinte configuração;
ax + by = gcd(a, b) = c
ex = gcd(e, (p - 1)(q - 1)) = 1 (I)
ax + by = gcd(a, b) = c (II)
a = e
b = (p - 1)(q - 1)
c = 1
ex + (p - 1)(q - 1)y = gcd(e, (p - 1)(q - 1)) = 1
E descobrimos os valores de x e de y aplicando o algoritmo estendido de Euclides.
O exercício nos garante que encontraremos uma solução para o problema, então não precisamos nos preocupar com isso.
3ª Etapa: definir os valores para p e q
Cuidados:
x pode ser um valor negativo na resolução da equação diofantina, pois se uma solução é possível, elas admitem infinitas soluções.
Porém, temos que:
e < (p - 1)(q - 1) (I)
ex = 1 -> e = 1 / x (II)
e (mod (p - 1)(q - 1)) * x = 1
ex (mod (p - 1)(q - 1)) = 1 (mod (p - 1)(q - 1))
e, x < (p - 1)(q - 1) = mod
Se x < 0, x = (x % mod + mod) % mod
Senão, x = x % mod
vector<bool> is_prime;
vector<int> primes;
void crivo(const int &n) {
is_prime = vector<bool>(n + 1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; i * i <= n; i++) {
if (is_prime[i]) {
for (int j = i * i; j <= n; j += i) {
is_prime[j] = false;
}
}
}
for (int i = 2; i <= n; i++) {
if (is_prime[i])
primes.push_back(i);
}
}
crivo(32000);
while (k--) {
int e, n, c, p, q;
cin >> e >> n >> c;
for (int i = 0; i < m; i++) {
p = primes[i];
if (n % p == 0 && is_prime[n / p]) {
q = n / p;
break;
}
}
int x, y, mod = (p - 1) * (q - 1);
extended_gcd(e, mod, x, y);
x = (x % mod + mod) % mod;
cout << pow_mod(c, x, n) << "\n";
}
ll pow_mod(ll b, ll x, ll mod) {
ll m = 1LL;
while (x) {
if (x & 1) {
m = (m * b) % mod;
}
b = (b * b) % mod;
x >>= 1;
}
return m;
}
É dado o início e o fim de um intervalo
O objetivo é saber qual o número com a maior sequência DDF nesse intervalo.
DDF -> Decimal Digit Factor Sequence
Confira na GIF abaixo:
ll soma_digitos(ll num){
ll sum = 0;
while(num){
sum += num%10;
num/=10;
}
return sum;
}
ll fatorar(ll n){
vector<ll> fator;
ll soma = 0;
for (ll i = 1; i * i <= n; i++){
if(n%i == 0){
if(n != i*i)soma += soma_digitos(n/i);
soma += soma_digitos(i);
}
}
return soma;
}
vector<ll> ddf [3001];
for(int i = 1; i <= 3000; i++){
ll ant = i, res = i;
ddf[i].push_back(i);
while(1){
res = fatorar(res);
if(ant == res)break;
ddf[i].push_back(res);
ant = res;
}
}