• [BZOJ 2242] [SDOI 2011] 计算器


    Description

    你被要求设计一个计算器完成以下三项任务:

    1. 给定 (y,z,p),计算 (y^z mod p) 的值;
    2. 给定 (y,z,p),计算满足 (xy≡ z pmod p) 的最小非负整数;
    3. 给定 (y,z,p),计算满足 (y^x ≡ z pmod p) 的最小非负整数。

    Input

    输入包含多组数据。

    第一行包含两个正整数 (T,K),分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。

    以下行每行包含三个正整数 (y,z,p),描述一个询问。

    Output

    对于每个询问,输出一行答案。

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

    Sample Input

    3 1
    2 1 3
    2 2 3
    2 3 3
    
    3 2
    2 1 3
    2 2 3
    2 3 3
    

    Sample Output

    2
    1
    2
    
    2
    1
    0
    

    HINT

    (1le y,z,ple 10^9)(p)为质数,(1le Tle10)

    Solution

    询问 (2)

    [axequiv bpmod p\ Downarrow\ ax-kp=b ]

    该方程有解的充要条件为 (gcd(a,p)mid b),答案为 (b imes a^{-1}mod p)

    询问 (3)

    给定 (a,b,p),求最小的非负整数 (x),满足

    [a^xequiv bpmod p ]

    根据费马小定理可知

    [a^xequiv a^{x mod p-1}pmod p ]

    因此 (x)(0) 枚举到 (p-2) 即可。

    (m={leftlceilsqrt p ight ceil},x=i imes m-j),有

    [a^{i imes m-j}equiv bpmod p ]

    移项得

    [(a^m)^iequiv a^jbpmod p ]

    首先从 (0dots m) 枚举 (j),将得到的 (a^jb) 的值存入 (hash) 表中,然后从 (1dots m) 枚举 (i),若表中存在 ((a^m)^i),则当前 (i imes m-j) 即为答案。

    Code

    #include <cmath>
    #include <cstdio>
    #include <tr1/unordered_map>
    
    std::tr1::unordered_map<int,int> hash;
    
    int read() {
    	int x = 0; char c = getchar();
    	while (c < '0' || c > '9') c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    	return x;
    }
    int gcd(int a, int b) {
    	return b ? gcd(b, a % b) : a;
    }
    int fastpow(int a, int b, int p) {
    	int res = 1;
    	for (; b; b >>= 1, a = 1LL * a * a % p)
    		if (b & 1) res = 1LL * res * a % p;
    	return res;
    }
    void bsgs(int a, int b, int p) {
    	if (a % p == 0) { puts("Orz, I cannot find x!"); return; }
    	int m = ceil(sqrt(p)), t = 1;
    	hash.clear(), hash[b % p] = 0;
    	for (int i = 1; i <= m; ++i)
    		t = 1LL * t * a % p, hash[1LL * t * b % p] = i;
    	a = t;
    	for (int i = 1; i <= m; ++i, t = 1LL * t * a % p)
    		if (hash.count(t)) { printf("%d
    ", i * m - hash[t]); return; }
    	puts("Orz, I cannot find x!");
    }
    int main() {
    	int T = read(), K = read();
    	while (T--) {
    		int a = read(), b = read(), p = read();
    		if (K == 1) printf("%d
    ", fastpow(a, b, p));
    		else if (K == 2) {
    			if (b % gcd(a, p)) puts("Orz, I cannot find x!");
    			else printf("%lld
    ", 1LL * b * fastpow(a, p - 2, p) % p);
    		} else bsgs(a, b, p);
    	}
    	return 0;
    }
    
    A man can be destroyed, but not defeated.
  • 相关阅读:
    GeoServer发布Shapfile、PostGIS数据
    Geoserver+Openlayers+MySQL设计思想,GeoServer服务器搭建(Docker构建镜像)
    Linux 输入输出重定向, &>file, 2>&1, 1>&2
    Git常用命令
    Java 操作 HBase 教程
    NATAPP--实现SSH内网穿透
    Spring boot banner
    ingress 密码验证
    rook 记录
    容器网络之网桥
  • 原文地址:https://www.cnblogs.com/fly-in-milkyway/p/10322617.html
Copyright © 2020-2023  润新知