• [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("
    ");
    	return 0;
    }
    

      

  • 相关阅读:
    PHPStrom 设置终端字体大小
    PostgreSQL 9 夸库查询
    弹性布局
    sql中的 where 、group by 和 having 用法解析
    数据库面试中常问的几个问题
    SQL中 UNION 和 UNION ALL 操作符小结
    SQL里 inner JOIN、 left (OUTER) JOIN 、right (OUTER) JOIN、 full (OUTER) JOIN 之间的区别
    MYSQL中LIMIT用法
    Java集合框架小结
    jQuery$.each循环遍历详解,各种取值对比,$.each遍历数组、对象、Dom元素、二维数组、双层循坏、类json数据等等
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4322674.html
Copyright © 2020-2023  润新知