• [BZOJ2242] 计算器 题解


    Description

    你被要求设计一个计算器完成以下三项任务:
    1、给定y,z,p,计算Y^Z Mod P 的值;
    2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;
    3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。
    Input

    输入包含多组数据。

    第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
    以下行每行包含三个正整数y,z,p,描述一个询问。
    Output

    对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。
    Sample Input

    【样例输入1】

    3 1

    2 1 3

    2 2 3

    2 3 3

    【样例输入2】

    3 2

    2 1 3

    2 2 3

    2 3 3

    【数据规模和约定】

    对于100%的数据,1<=y,z,p<=10^9,P为质数,1<=T<=10。
    Sample Output

    【样例输出1】

    2

    1

    2

    【样例输出2】

    2

    1

    0


    思路:将本题的3个任务拆分来看,任务1就是快速幂模板,任务2就是用exgcd求解不定方程,任务3就是 Baby Step Giant Step求解高次同余方程.那么3个模板凑在一起分别操作即可


    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <ctime>
    #include <map>
    using namespace std;
    #define rg register
    #define LL long long
    #define __space putchar(' ')
    #define __endl putchar('
    ')
    #define debug printf("Time Test:%d
    ",clock())
    template <typename qwq> inline void read(qwq & x)
    {
    	x = 0;
    	rg int f = 1;
    	rg char c = getchar();
    	while (c < '0' || c > '9')
    	{
    		if (c == '-') f = -1;
    		c = getchar();
    	}
    	while (c >= '0' && c <= '9')
    	{
    		x = (x << 1) + (x << 3) + (c ^ 48);
    		c = getchar();
    	}
    	x *= f;
    }
    template <typename qaq> inline void print(qaq x)
    {
    	if (x < 0)
    	{
    		putchar('-');
    		x = -x;
    	}
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + '0');
    }
    int p;
    inline LL Pow(LL x,LL y)
    {
    	rg LL ret = 1;
    	while(y)
    	{
    		if (y & 1) ret = ret * x % p;
    		x = x * x % p;
    		y >>= 1;
    	}
    	return ret % p;
    }
    inline LL exgcd(LL a,LL b,LL & x,LL & y)
    {
    	if (!b)
    	{
    		x = 1,y = 0;
    		return a;
    	}
    	rg LL temp = exgcd(b,a % b,x,y);
    	rg LL t = x;
    	x = y;
    	y = t - a / b * y;
    	return temp;
    }
    map<int,int> hash;
    inline int Baby_Step_Giant_Step(int a,int b)
    {
    	hash.clear();
    	b %= p;
    	rg int t = ceil(sqrt(p));
    	for (rg int j = 0; j < t; ++j)
    	{
    		rg int val = (LL) b * Pow(a,j) % p; //b * a ^ j;
    		hash[val] = j;
    	}
    	a = Pow(a,t); //a ^ t
    	if (!a) return !b ? 1 : -1;
    	for (rg int i = 0; i <= t; ++i)
    	{
    		rg int val = Pow(a,i); //(a ^ t) ^ i
    		rg int j = hash.find(val) == hash.end() ? -1 : hash[val];
    		if (j >= 0 && i * t - j >= 0) return i * t - j;
    	}
    	return -1;
    }
    int t,k,y,z;
    LL xx,yy;
    inline void work1()
    {
    	print(Pow(y,z)),__endl;
    	return;
    }
    inline void work2()
    {
    	rg LL gcd = exgcd(y,p,xx,yy);
    	if (z % gcd)
    	{
    		puts("Orz, I cannot find x!");
    		return;
    	}
    	rg LL temp = p / gcd;
    	while (xx < 0) xx += temp;
    	print(((xx * z / gcd) % temp + temp) % temp),__endl;
    }
    inline void work3()
    {
    	rg LL ans = Baby_Step_Giant_Step(y,z);
    	if (ans == -1 ) puts("Orz, I cannot find x!");
    	else print(ans),__endl;
    	return;
    }
    int main()
    {
    	read(t),read(k);
    	while (t--)
    	{
    		read(y),read(z),read(p);
    		switch (k)
    		{
    			case 1:
    				work1();
    				break;
    			case 2:
    				work2();
    				break;
    			case 3:
    				work3();
    				break;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    450. K组翻转链表
    6. 合并排序数组 II
    64. 合并排序数组
    165. 合并两个排序链表
    103. 带环链表 II
    102. 带环链表
    [web安全原理]PHP命令执行漏洞基础
    [原题复现]-HITCON 2016 WEB《babytrick》[反序列化]
    《将博客搬至CSDN》
    PHP反序列化漏洞-CVE-2016-7124(绕过__wakeup)复现
  • 原文地址:https://www.cnblogs.com/Here-is-SG/p/10702907.html
Copyright © 2020-2023  润新知