zoukankan      html  css  js  c++  java
  • BZOJ2242: [SDOI2011]计算器

    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

    Solution

    这种强行拼题真的好吗...
    (一道题当T1,T2,T3用)
    其实是板子题来着
    第一问显然直接快速幂,第二问是exgcd,第三问是bsgs
    这里讲一下bsgs的过程:

    [已知量:Yspace Pspace Zspace m\ Y^xspace equiv Zspace (modspace p)\ 求x\ 设m=lceil sqrt{P} ceil\ 则x=i*m-j \ Y^{i*m-j}equiv Z(modspace P)\ Y^{i*m}equiv(Z*Y^j) (modspace P)\ ]

    所以只需要开一个map,存一下(Z*Y^j)的值,然后枚举i,第一个枚举出来的答案就是最小值

    #include <bits/stdc++.h>
    #define ll long long
    
    int T, k;
    ll y, z, p;
    
    ll power(ll a, ll b) {
        ll ans = 1, base = a;
        while(b) {
            if(b & 1) ans = (ans * base) % p;
            base = (base * base) % p;
            b >>= 1;
        }
        return ans % p;
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y) {
        if(b == 0) {return x = 1, y = 0, a;}
        ll ans = exgcd(b, a % b, x, y), tmp = x;
        x = y; y = tmp - (a / b) * y;
        return ans;
    }
    
    std::map<ll , ll> mp;
    void bsgs() {
        mp.clear(); z %= p;
        ll m = std::sqrt(p); if(m % p) ++ m; 
        for(ll i = 0, tmp = 1; i <= m; i ++, tmp = tmp * y % p) {
        	mp[z * tmp % p] = i;
        }
        if(power(y , m) == 0) {
        	if(z == 1) puts("1");
        	else puts("Orz, I cannot find x!");
        	return;
        }
        for(ll i = 1; i <= m; i ++) {
        	ll tmp = power(y, i * m), j = mp[tmp];
        	if(j == 0) continue;
        	if(i * m - j >= 0) {
        		printf("%lld
    ", i * m - j);
        		return;
        	}
        }
        puts("Orz, I cannot find x!");
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif 
        scanf("%d%d", &T, &k);
        while(T--) {
            scanf("%lld%lld%lld", &y, &z, &p);
            if(k == 1) {
                printf("%lld
    ", power(y, z));
            } else if(k == 2) {
                ll a1, a2, g;
                y %= p; z %= p;
                g = exgcd(y ,p ,a1 ,a2);
                if(z % g) puts("Orz, I cannot find x!"); 
                else {
                    ll tmp = p / g;
                    a1 = ((a1 * z) % tmp + tmp) % tmp;
                    printf("%lld
    ", a1);
                }
            } else bsgs();
        }
        return 0;
    }
    
  • 相关阅读:
    Python3安装
    HTML基础
    Python Socket
    python常用模块
    JSON.stringify的三个参数
    判断数组中存在重复元素
    vant-ui表单验证
    如何计算出浏览器的帧数?requestAnimationFrame
    js判断两个区间是否存在交集
    怎么在组件内部判断出是否插入了slot
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10126059.html
Copyright © 2011-2022 走看看