[UOJ 74] 【UR #6】破解密码

题目链接:UOJ - 74

题目分析

题目中,将字符串 S 的第一个字符移到末尾,其他字符向前移动一个位置,f(S) 就从 Hi 变成了 Hi+1。

我们分析一下这个过程:假设第一个字符为 c, (Hi - 26^(n-1) * c) * 26 + c = Hi+1

26 * Hi - Hi+1 = (26^n - 1) * c

c = (26 * Hi - Hi+1) * Inv(26^n - 1)

那么每一个 c 都可以直接解出来,由于题目保证有解,所以每一个 c 解出来的一定都是 [0, 25] 的数。

嗯..看起来非常对..提交上去....WA.50

为什么只得了50分呢?因为:“有除法的时候一定要考虑没有逆元的情况!

当 (26^n - 1) % p = 0 的时候,26^n - 1 是没有逆元的。而这样的点在数据里有 5 个 【QAQ】。

这样在前面的方程 26 * Hi - Hi+1 = (26^n - 1) * c 中含有 c 的项系数为 0,被消去,变成了 Hi * 26 = Hi+1 。

因为方程与 c 无关,所以 c 是任何一个字母这个方程都可以成立。

那么就要根据 f(S) = Hi 来求出这个 S 了,我们知道 f(S) 相当于是把字符串看做一个 26 进制数,然后这里的 Hi * 26 = Hi+1。

所以我们把 H0 看做26进制数求出对应的字符串,之后向左移一位就相当于将 H 乘了 26 ,依然是符合 f(S) = Hi+1 的。

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

const int MaxN = 100000 + 5;

typedef long long LL;

int n, p, t;
int H[MaxN]; 

LL A0, Temp;
LL X[MaxN];

LL Pow(LL a, int b)
{
	LL ret = 1, f = a;
	while (b)
	{
		if (b & 1)
		{
			ret *= f;
			ret %= p;
		}
		b >>= 1;
		f *= f;
		f %= p;
	}
	return ret;
}

LL NY(LL x)
{
	x = ((x % p) + p) % p;
	return Pow(x, p - 2);
}

int main()
{
	scanf("%d%d", &n, &p);
	for (int i = 0; i < n; ++i) scanf("%d", &H[i]);
	if (Pow(26ll, n) != 1)
	{
		Temp = NY(Pow(26ll, n) - 1);
		for (int i = 0; i < n; ++i)
		{
			if (i == n - 1) t = 0;
			else t = i + 1;
			X[i] = ((LL)H[i] * 26 - (LL)H[t]) % p * Temp;
			X[i] = ((X[i] % p) + p) % p;
		}
	}
	else
	{
		int Pos = n;
		while (H[0])
		{
			X[--Pos] = H[0] % 26;
			H[0] /= 26;
		}
	}
	for (int i = 0; i < n; ++i) printf("%c", ‘a‘ + X[i]);
	printf("\n");
	return 0;
}

  

时间: 2024-10-16 13:08:01

[UOJ 74] 【UR #6】破解密码的相关文章

UR 6 破解密码

SOL : 我们发现 ha[i]=ha[i-1]*26-head*26^(len+1)+head head是指当前把这玩意扔到队尾的东东.就好了. 还有就是考虑没有逆元的情况. #include<bits/stdc++.h> #define LL long long #define N 100007 using namespace std; int mo,n,h[N],t; char ans[N]; LL qsm(LL x,LL y=mo-2) { static LL anw; for (an

【安全牛学习笔记】COWPATTY 破解密码

HTTP://ETUORLASLS.ORG/NETWORKING/802.11+SECURITY.+WI-FI+PROTECTED+ACCESS+AND+802.11I/ TR破解密码 测试效果 john --wordlist=password.lst --rules --stdout | grep -i Password123 破解调用 john --wordlist=pass.list --rules --stdout | aircrack-ng -e kifi -w wpa.cap 北京联

Linux_破解密码-营救模式

实验用机:CentOS 5.7 破解密码 设置开机启动界面 系统运行级别 营救模式 一.破解密码 root用户可以更改任何用户的密码,普通用户只能修改自己的密码. 步骤: 1.重新启动系统 2.开机倒数时间内,敲任意键 3.按字母e去编辑 4.选择kernel 开头的行,再次按字母e 编辑 然后敲空格 输入数字1,再敲回车 进入单用户模式,破解密码.(此模式绕过密码验证) 5.按字母键b 去引导进入系统 6.直接passwd 修改root用户的密码 7.输入init 5或者init 3 进入系统

Windows系统忘记密码怎么办?如何破解密码?(亲测可用)

国外有一个工具:LazesoftRecoverMyPassword软件,可用于系统密码破解与清除工具,它可以轻松移除 Windows 系统的登录密码,快速破解与清除电脑开机密码,也可以重置密码或者设置为空密码,解锁被锁定或禁用的用户帐户.其原理就是通过创建一个启动盘来破解Windows开机密码. 所需软件: (1)LazesoftRecoverMyPassword软件 (2)UltraISO软件 具体步骤如下: 1.下载并安装LazesoftRecoverMyPassword软件: 2.生成镜像

mysql数据库破解密码

mysql数据库密码破解大揭秘 rpm包安装的 数据库管理员密码的恢复 首先停止mysql服务, service  mysql  stop service  mysql  start  --skip-grant-table  然后以跳过权限方式后台启动 mysql    执行mysql回车进入mysql,然后修改密码 mysql> Use mysql数据库,然后执行如下命令: 把root用户密码修改为999 update      mysql.user  set  password=passwo

Centos Linux 系统破解密码 &nbsp;

Centos Linux 系统密码破解 本破解使用单用户模式手工破解 使用系统:Centos 5/6 进入开机界面时,按"↓"进入GRUB 界面,如下图所示: 根据提示按"e"编辑,会出现如下图所示: 选择第2选项,继续按"e"编辑,在最后添加"single",如下图所示: 按"Enter"键保存,会自动回到上级界面,按"b"键会自动从单用户模式重启,重启会自动登录到单用户模式,如下图所

windows server2008破解密码不用系统光盘

今天突然想起密码破解这个事,决定把我找出来的办法说一下,不知道老外有没有这么做过!网上搜到的windows server2008破解密码都是需要光盘,但在破解的时候是需要原装的光盘,起初也这么认为,找不到原装光盘只能重装了:后来还是不死心,就决定研究一下,还是有了结果.还是需要工具:一个pe系统(一个ghost系统盘或者PEu盘):接下来进入正题! 1.给机器装上ghost启动盘或者pe U盘/启动盘,设置bios-boot启动项: (在这是用的ghost系统盘),然后F10保存重启. 2.进入

当今破解密码涉及的思路方法总结

破解网络密码-暴力穷举 密码破解技术中最基本的就是暴力破解,也叫密码穷举.如果黑客事先知道了账户号码,如邮件帐号.QQ用户帐号.网上银行账号等,而用户的密码又设置的十分简单,比如用简单的数字组合,黑客使用暴力破解工具很快就可以破解出密码来.因此用户要尽量将密码设置的复杂一些. 破解网络密码-击键记录 如果用户密码较为复杂,那么就难以使用暴力穷举的方式破解,这时黑客往往通过给用户安装木马病毒,设计"击键记录"程序,记录和监听用户的击键操作,然后通过各种方式将记录下来的用户击键内容传送给黑

CentOS7 破解密码

解决方法 CentOS 7.3系统 1. 重启系统后出现以下界面 2.选择GRUB界面在引导装载程序菜单上,用上下方向键选择你忘记密码的那个系统键入"e" 进入以下界面 3. 在GRUB界面使用向下方向键移动到linux16行 4. 在此行行尾键入"init=/bin/sh"  使用组合键ctrl x启动        5. 由于/目录文件系统是只读,需要重新挂载/目录 6.关闭selinux vim /etc/sysconfig/selinxu SELINUX=d