BZOJ 2242 SDOI2011 计算器 快速幂+扩展欧几里得+BSGS

42 篇文章 0 订阅

题目大意:……简洁明了自己看

第一问快速幂

第二问扩展欧几里得

第三问BSGS

顺便一开始没看到p是质数0.0 去弄了EXBSGS的模板0.0 懒得改了

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 1001001
using namespace std;
typedef long long ll;  
typedef pair<ll,ll> abcd;  
ll A,B,C,D,hash_table[M],val[M],tim[M],tot;  
int Hash(ll x)  
{  
    int pos=x%M;  
    while(1)  
    {  
        if(tim[pos]!=tot)  
            tim[pos]=tot,hash_table[pos]=-1,val[pos]=0x3f3f3f3f;  
        if(hash_table[pos]==-1||hash_table[pos]==x)  
            return hash_table[pos]=x,pos;  
        else  
            ++pos,pos%=M;  
    }  
}  
int Get_Hash(ll x)  
{  
    int pos=x%M;  
    while(1)  
    {  
        if(tim[pos]!=tot)  
            tim[pos]=tot,hash_table[pos]=-1;  
        if(hash_table[pos]==-1)  
            return -1;  
        if(hash_table[pos]==x)  
            return pos;  
        else  
            ++pos,pos%=M;  
    }  
}  
ll GCD(ll x,ll y)  
{  
    return y?GCD(y,x%y):x;  
}  
abcd EXGCD(ll x,ll y)  
{  
    if(!y) return abcd(1,0);  
    abcd temp=EXGCD(y,x%y);  
    return abcd(temp.second,temp.first-x/y*temp.second);  
}  
ll Inverse(ll x)  
{  
    ll temp=EXGCD(x,C).first;  
    return (temp%C+C)%C;  
}  
ll EXBSGS()  
{  
    ll i,m,cnt=0,temp,base=1;  
    int pos;  
    B%=C;  
    for(i=0,temp=1%C;i<=50;i++,temp*=A,temp%=C)  
        if(temp==B)  
            return i;  
    D=1;  
    while(temp=GCD(A,C),temp!=1)  
    {  
        if(B%temp)  
            return -1;  
        ++cnt;  
        B/=temp;  
        C/=temp;  
        D*=A/temp;  
        D%=C;  
    }  
    B*=Inverse(D);B%=C;  
    m=(ll)ceil(sqrt(C)+1e-5);  
    ++tot;  
    for(i=0,temp=1%C;i<m;i++,temp*=A,temp%=C)  
        pos=Hash(temp),val[pos]=min(val[pos],i);  
    for(i=1,base=1%C;i<=m;i++,base*=A,base%=C);  
    for(i=0,D=1%C;i<m;i++,D*=base,D%=C)  
    {  
        temp=EXGCD(D,C).first*B;  
        temp=(temp%C+C)%C;  
        pos=Get_Hash(temp);  
        if(~pos)  
            return i*m+val[pos]+cnt;  
    }  
    return -1;  
}
ll KSM()
{
	ll re=1;
	while(B)
	{
		if(B&1)re*=A,re%=C;
		A*=A,A%=C;
		B>>=1;
	}
	return re;
}
ll EXGCD()
{
	if(A%C==0&&B%C!=0)
		return -1;
	return (EXGCD(A,C).first%C*B%C+C)%C;
}
int main()
{
	int T,k;
	ll ans;
	for(cin>>T>>k;T;T--)
	{
		cin>>A>>B>>C;
		switch(k)
		{
			case 1:ans=KSM();break;
			case 2:ans=EXGCD();break;
			case 3:ans=EXBSGS();break;
		}
		if(ans==-1)
			puts("Orz, I cannot find x!");
		else
			cout<<ans<<endl;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值