LightOJ - 1341 Aladdin and the Flying Carpet (Pollard_Rho分解)

思路:

用Pollard_Rho做质因子分解,dfs枚举所有因子判断是否合法;
由于当\(b*b>a\)时一定无解,因此这里还可以提前判断一下;
我看其他题解的做法基本都是枚举素数做质因子分解(1E6以内素数有78498个),而\(Test\)是4e3组,这复杂度已经很高了,更离谱的是有人枚举1-b(b<1e6) ;

代码:

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef __int128 LL;
typedef unsigned long long uLL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
typedef pair<double,double> pdd;
const int N=1e5+5;
const int M=4e4+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int S=100;
#define ls (i<<1)
#define rs (i<<1|1)
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define mk make_pair
#define mem(a,b) memset(a,b,sizeof(a))
LL read()
{
    LL x=0,t=1;
    char ch;
    while((ch=getchar())<'0'||ch>'9') if(ch=='-') t=-1;
    while(ch>='0'&&ch<='9'){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); }
    return x*t;
}
std::mt19937 rnd(233);
LL factor[N];
int tot;
LL gcd(LL x,LL y)
{
    return y?gcd(y,x%y):x;
}

inline LL mul(LL a,LL b,LL p)
{
    return a*b%p;
}

//LL mul(LL a,LL b,LL p)
//{
//    LL res=0;
//    while(b)
//    {
//        if(b&1) res=(res+a)%p;
//        a=(a+a)%p;
//        b>>=1;
//    }
//    return res;
//}
inline LL power(LL a,LL b,LL p)
{
    LL res=1;
    while(b)
    {
        if(b&1) res=mul(res,a,p);
        a=mul(a,a,p);
        b>>=1;
    }
    return res;
}
inline bool check(LL a,LL n,LL d,LL cnt)
{
    LL res=power(a,d,n);
    LL las=res;
    for(int i=1;i<=cnt;i++)
    {
        res=mul(res,res,n);
        if(res==1&&las!=1&&las!=n-1) return 1;
        las=res;
    }
    if(res!=1) return 1;
    return 0;
}
bool MR(LL n)
{
    if(n<2) return 0;
    if(n==2) return 1;
    if((n&1)==0) return 0;
    LL d=n-1,cnt=0;
    while((d&1)==0) d>>=1,cnt++;
    for(int i=1;i<=S;i++)
    {
        LL a=rnd()%(n-1)+1;
        if(check(a,n,d,cnt)) return 0;

    }
    return 1;
}
LL PR(LL n,LL k)
{
    LL u=2,v=1;
    LL x=rnd()%(n-1)+1;
    LL y=x;
    while(1)
    {
        x=(mul(x,x,n)+k)%n;
        v++;
        LL d=gcd((y-x+n)%n,n);
        if(d>1&&d<=n) return d;
        if(v==u)
        {
            y=x;
            u<<=1;
        }
    }
}
void divide(LL n,LL k)
{
    if(n==1) return ;
    if(MR(n)) return (void)(factor[++tot]=n);
    LL d=n,c=k;
    while(d==n) d=PR(n,--c);
    divide(d,c);
    divide(n/d,c);
}
long long ans;
LL a,b;
LL c[N],cnt[N];
void dfs(int len,LL x)
{
    //printf("%d , %lld\n",len,x);
    if(len==0){
        if(min(x,a/x)>=b&&x!=a/x) ans++;
        return ;
    }
    dfs(len-1,x);
    for(int i=1;i<=cnt[len];i++)
    {
        x*=c[len];
        dfs(len-1,x);
    }
}
int main()
{
    int T=read();
    int cas=0;
    while(T--)
    {
        ans=tot=0;
        a=read(),b=read();
        divide(a,S);
        sort(factor,factor+1+tot);
        for(int i=1;i<=tot;i++) c[i]=factor[i];
        unique(c+1,c+tot+1);
        int len=0;
        for(int i=1;i<=tot;i++)
        {
            if(factor[i]!=factor[i-1]) len++;
            cnt[len]++;
        }
        dfs(len,1);
        for(int i=1;i<=len;i++) cnt[i]=0;
        printf("Case %d: %lld\n",++cas,ans>>1);
    }
    return 0;
}
/*
20
1000000000000 2
963761198400 5
963761198400 5
963761198400 5
963761198400 5
1000000000000 2
963761198400 5
963761198400 5
963761198400 5
963761198400 5
1000000000000 500000
963761198400 5
963761198400 5
963761198400 5
963761198400 100
*/

附一张因子个数图,前者为因子最多的数字,后者为其因子数量;(源自知乎)

posted @ 2021-08-22 21:48  DeepJay  阅读(202)  评论(0编辑  收藏  举报