• [BZOJ2242][SDOI2011]计算器


    [BZOJ2242][SDOI2011]计算器

    试题描述

    你被要求设计一个计算器完成以下三项任务:
    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)的最小非负整数。

    输入

    输入包含多组数据。

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

    输出

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

    输入示例

    3 1
    2 1 3
    2 2 3
    2 3 3

    输出示例

    2
    1
    2

    数据规模及约定

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

    题解

    第一问快速幂,第二问求逆元,第三问用 BSGS。

    BSGS 就是中途相遇的一个应用,我们可以令 x = km + b,于是有 ykm Ξ z·y-b (mod p),那么当 m = sqrt(n) 时,k 和 b 都不超过 sqrt(n),所以我们先枚举 b,然后把所有的 z·y-b 扔进 hash,然后再枚举 k 看看能不能匹配上。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define LL long long
    #define oo 2147483647
    
    LL Pow(int a, int b, int p) {
    	LL ans = 1, t = a;
    	while(b) {
    		if(b & 1) (ans *= t) %= p;
    		(t *= t) %= p; b >>= 1;
    	}
    	return ans;
    }
    
    void gcd(int a, int b, LL& x, LL& y) {
    	if(!b){ x = 1; y = 0; return ; }
    	gcd(b, a % b, y, x); y -= a / b * x;
    	return ;
    }
    LL Inv(int y, int p) {
    	if(y % p == 0) return -233;
    	LL x, k;
    	gcd(y, p, x, k);
    	return (x % p + p) % p;
    }
    
    #define maxn 100010
    #define MOD 100007
    int ToT, head[maxn], nxt[maxn], num[maxn];
    LL val[maxn];
    int Find(LL x) {
    	int u = x % MOD;
    	for(int e = head[u]; e; e = nxt[e]) if(val[e] == x) return num[e];
    	return -233;
    }
    void Insert(LL x, int v) {
    	int u = x % MOD;
    	nxt[++ToT] = head[u]; val[ToT] = x; num[ToT] = v; head[u] = ToT;
    	return ;
    }
    
    int main() {
    	int T = read(), K = read();
    	while(T--) {
    		int y = read(), z = read(), p = read();
    		if(K == 1) printf("%d
    ", (int)Pow(y, z, p));
    		if(K == 2) {
    			LL tmp = Inv(y, p);
    			if(tmp < 0) puts("Orz, I cannot find x!");
    			else printf("%d
    ", (int)(tmp * z % p));
    		}
    		if(K == 3) {
    			if(y % p == 0){ puts("Orz, I cannot find x!"); continue; }
    			int m = sqrt(p);
    			memset(head, 0, sizeof(head)); ToT = 0;
    			LL val = z % p, invy = Inv(y, p);
    			for(int i = 0; i < m; i++, (val *= invy) %= p)
    				if(Find(val) < 0) Insert(val, i);
    			val = 1;
    			bool ok = 0;
    			for(int i = 0; i * m <= p; i++, (val *= Pow(y, m, p)) %= p) if(Find(val) >= 0) {
    				printf("%d
    ", i * m + Find(val)); ok = 1; break;
    			}
    			if(!ok) puts("Orz, I cannot find x!");
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    python走起之第十七话
    python走起之第十五话
    python走起之第十四话
    python走起之第十三话
    python走起之第十二话
    python走起之第十一话
    python走起之第九话
    python走起之第九话
    python走起之第八话
    python走起之第六话
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6697711.html
Copyright © 2020-2023  润新知