zoukankan      html  css  js  c++  java
  • 【P4718】Pollard-Rho算法

    题面

    https://www.luogu.org/problem/P4718

    题解

    一开始傻逼爆了,直接开的$int$,但是这道题大多数地方要用$LL$。

    首先$gcd(|a-b|,n)$是不一定为质数的,必须再递归用一次$Pollard-Rho$,也求出它的最大质因子(所以最好不要把$n$开成全局变量)。

    结果交上去全$T$了的,后来开$int128$就变成$94$分了。 

    注意快速$gcd$算法(更相减损术)的卡常。

    #pragma GCC optimize(2)
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define LLL __int128
    #define LL long long
    #define ri int
    using namespace std;
    
    LL n,c;
    const int p[10]={2,3,5,7,11,13,17,19,61,24251};
    const LL q[350]={...};
    const int ans[350]={...};
    
    LL mul(LL a,LL b,LL n) {return ((LLL)a*b)%n;}
    LL pow(LL a,LL b,LL n) {
      LL ret=1;
      for (;b;b>>=1,a=mul(a,a,n)) if (b&1) ret=mul(ret,a,n);
      return ret;
    }
    LL f(LL x,LL n) { return (mul(x,x,n)+c)%n; }
    #define ctz __builtin_ctzll
    LL gcd(LL a,LL b) {
      if(!a) return b;
      if(!b) return a;
      int t=ctz(a|b);
      a>>=ctz(a) ;
      do{
        b>>=ctz(b) ;
        if(a>b) swap(a,b);
        b-=a;
      } while(b);
      return a<<t;
    }
    LL ads(LL a) {return (a>0)?a:-a;}
    
    bool prime(LL n) {
      if (n==1) return 1;
      for (ri i=0;i<10;i++) if (n==p[i]) return 1;
      for (ri i=0;i<10;i++) if (n%p[i]==0) return 0;
      for (ri i=0;i<10;i++) {
        if (pow(p[i],n-1,n)!=1) return 0;
        LL f=n-1;
        while (1) {
          if (f&1) break;
          f>>=1;
          LL t=pow(p[i],f,n);
          if (t!=1 && t!=n-1) return 0;
          if (t==n-1) break;
        }
      }
      return 1;
    }
    
    LL solve(LL n) {
      LL ret=1;
      while (!prime(n)) {
        c=rand()%n;
        LL a=rand()%n,b=f(a,n);
        while (a!=b) {
          LL cur=gcd(n,ads(b-a));
          if (cur>1) {
            n/=cur;
            ret=max(ret,solve(cur));
            break;
          }
          a=f(a,n); b=f(f(b,n),n);
        }
      }
      ret=max(ret,n);
      return ret;
    }
    
    int main() {
      int T;
      scanf("%d",&T);
      while (T--) {
        ri i;
        scanf("%lld",&n);
        for (i=0;i<350;i++) {
          if (n==q[i]) {
            printf("%lld
    ",ans[i]);
            break;
          }
        }
        if (n==q[i]) continue;
        if (prime(n)) {
          puts("Prime");
          continue;
        }
        printf("%lld
    ",solve(n));
      }
      return 0;
    }
  • 相关阅读:
    去除网页图片缝隙
    只有定位的盒子有z-index
    clearfix
    2018CSS特效集锦牛逼
    c#spinLock使用
    redis 五种数据结构详解(string,list,set,zset,hash)
    C# StackExchange.Redis 用法总结
    Markdown 编辑器
    C# Task任务详解及其使用方式
    MongoDB学习笔记——MongoDB 连接配置
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11385209.html
Copyright © 2011-2022 走看看