当前位置: 代码迷 >> 综合 >> 【数学一本通 第一章】计算器 [LUOGU P2485] [SDOI 2011] [CODEVS 1565] [BZOJ 2242]
  详细解决方案

【数学一本通 第一章】计算器 [LUOGU P2485] [SDOI 2011] [CODEVS 1565] [BZOJ 2242]

热度:36   发布时间:2024-01-17 00:13:02.0

题目:

题目链接:计算器
题解:
一道三个小函数的集合,一道板子题,写个博客记录一下,还是要先%%%%%%%hsm%%%%%%%帮我找到了错误,一定要记得是扩展BSGS(就是处理一下非素数的情况,就是除一下gcd即可),还是没好好看题啊,,(〃>_<;〃),

代码:

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
LL yy,z,p,n,k,a,b;
class hash 
{
    public:hash(){
    memset(a,0xff,sizeof(a));}int locate(LL x){
    LL l=x%MOD;while(a[l]!=x&&a[l]!=-1) l=(l+1)%MOD;return l;}void insert(LL x,LL va){
    LL l=locate(x);if(a[l]==-1) a[l]=x,v[l]=va;}LL get(LL x) {
    LL l=locate(x);return a[l]==x?v[l]:-1;}void clear(){
    memset(a,0xff,sizeof(a));}private:static const LL MOD=100007;LL a[MOD+100],v[MOD+100];
}H;
LL ksm(LL a,LL b,LL mod)
{
    LL s=1;while(b){
    if(1&b) s=(s*a)%mod;b>>=1;  a=(a*a)%mod;}return s;
}
LL exgcd1(LL a,LL b,LL &x ,LL &y)
{
    LL t,s;if(!b){
    x=1,y=0; return a;}s=exgcd1(b,a%b,x,y);t=x,x=y,y=t-a/b*y;return s;
}
LL Gcd(LL a,LL b){
    return b?Gcd(b,a%b):a;}
void BSGS(LL yy,LL z,LL p)//扩展BSGS
{
    LL d=1,y,x,m,t=1;if(yy==0&&z==0){
    printf("1\n");return;}if(yy==0&&z!=0){
    printf("Orz, I cannot find x!\n");return ;}H.clear();m=ceil(sqrt(double(p)));LL tmp=1,cnt=0l;LL gcd=Gcd(yy,p);while(gcd!=1)//对于非素数的处理{
    if(z%gcd!=0) {
    printf("Orz, I cannot find x!\n");return ;}z/=gcd; p=gcd; tmp*=(yy/gcd)%p;cnt++;}for(int i=0;i<m;i++) H.insert(t,i),t=t*yy%p;for(int i=0;i<m;i++){
    exgcd1(d,p,x,y);x=((x*z)%p+p)%p; y=H.get(x);if(y!=-1) {
    printf("%lld\n",i*m+y);return;}d=(d*t)%p;}printf("Orz, I cannot find x!\n");return ;
}
int main()
{
    
// freopen("a.txt","r",stdin);scanf("%lld%lld",&n,&k);if(k==1)//快速幂即可 {
     for(int i=1;i<=n;i++){
    scanf("%lld%lld%lld",&yy,&z,&p);printf("%lld\n",ksm(yy,z,p));}}else if(k==2)//直接exgcd即可 {
    for(int i=1;i<=n;i++){
    scanf("%lld%lld%lld",&yy,&z,&p);LL x,y;LL gcd=exgcd1(yy,p,x,y);if(z%gcd)  puts("Orz, I cannot find x!");else{
    int tm=p/gcd;while(x<0) x+=tm;printf("%lld\n",((x*z/gcd)%tm+tm)%tm);}  }}else//扩展BSGS的板子即可(千万记得是扩展!!!) {
    for(int i=1;i<=n;i++){
    scanf("%lld%lld%lld",&yy,&z,&p);BSGS(yy,z,p);}}return 0;
}

continue……

  相关解决方案