zoukankan      html  css  js  c++  java
  • BZOJ2082 : [Poi2010]Divine divisor

    将所有数分解质因数,那么第一问就是求指数的最大值,第二问就是$2^{指数最大的质数个数}-1$。

    首先将$10^6$以内的质因数全部找到,那么剩下部分的因子$>10^6$,且只有3种情况:

    1.大质数

    2.大质数的平方

    3.两个大质数的乘积

    对于1可以用MillerRabin算法判定,对于2可以尝试开根号然后判定。

    那么剩下的一定是3,对于每个不确定的数字,如果它所含的因子只有它有,那么这两个因子可以合并,算第二问的时候个数$+=2$即可。

    判断其它数字是否也有这个因子,只需要求gcd即可。

    时间复杂度$O(frac{nv^{frac{1}{3}}}{ln v})$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    typedef long long ll;
    const int N=1000000,B=10000,MAXL=220;
    int n,i,j,k,tot,p[N],v[N],ca,cb,cc,ans0,ans1;ll a[64*600],b[610],c[610];
    inline ll gcd(ll a,ll b){
      ll c=1;
      while(a-b){
        if(a&1){
          if(b&1){
            if(a>b)a=(a-b)>>1;else b=(b-a)>>1;
          }else b>>=1;
        }else{
          if(b&1)a>>=1;else c<<=1,a>>=1,b>>=1;
        }
      }
      return c*a;
    }
    inline ll mul(ll a,ll b,ll n){return(a*b-(ll)(a/(long double)n*b+1e-3)*n+n)%n;}
    inline ll pow(ll a,ll b,ll n){
      ll d=1;a%=n;
      while(b){
        if(b&1)d=mul(d,a,n);
        a=mul(a,a,n);
        b>>=1;
      }
      return d;
    }
    inline bool check(ll a,ll n){
      ll m=n-1,x,y;int i,j=0;
      while(!(m&1))m>>=1,j++;
      x=pow(a,m,n);
      for(i=1;i<=j;x=y,i++){
        y=pow(x,2,n);
        if((y==1)&&(x!=1)&&(x!=n-1))return 1;
      }
      return y!=1;
    }
    inline bool miller_rabin(ll n){
      int t=5;ll a;
      if(!(n&1))return 0;
      while(t--)if(check(rand()%(n-1)+1,n))return 0;
      return 1;
    }
    inline ll getsqrt(ll n){
      ll x=sqrt(n);
      for(ll i=x-2;i<=x+2;i++)if(i*i==n)return i;
      return 0;
    }
    inline void divide(){
      ll n;
      scanf("%lld",&n);
      for(int i=0;i<tot&&p[i]<=n;i++)while(n%p[i]==0)n/=p[i],a[++ca]=p[i];
      if(n==1)return;
      if(miller_rabin(n)){a[++ca]=c[++cc]=n;return;}
      ll t=getsqrt(n);
      if(t){a[++ca]=t;a[++ca]=c[++cc]=t;return;}
      b[++cb]=n;
    }
    inline void solve(ll n){
      for(int i=1;i<=cc;i++)if(n%c[i]==0){
        a[++ca]=c[i],a[++ca]=n/c[i];
        return;
      }
      for(int i=1;i<=cb;i++){
        ll t=gcd(n,b[i]);
        if(t==1||t==n)continue;
        a[++ca]=t,a[++ca]=n/t;
        return;
      }
      a[++ca]=-n;
    }
    struct Num{
      int a[MAXL],len,fu;
      Num(){len=1,fu=a[1]=0;}
      Num operator+(const Num&b){
        Num c;
        c.len=max(len,b.len)+2;
        int i;
        for(i=1;i<=c.len;i++)c.a[i]=0;
        if(fu==b.fu){
          for(i=1;i<=len;i++)c.a[i]=a[i];
          for(i=1;i<=b.len;i++)c.a[i]+=b.a[i];
          for(i=1;i<=c.len;i++)if(c.a[i]>=B)c.a[i+1]++,c.a[i]-=B;
          while(c.len>1&&!c.a[c.len])c.len--;
          c.fu=fu;
        }else{
          bool flag=0;
          if(len==b.len){
            for(i=len;i;i--)if(a[i]!=b.a[i]){
              if(a[i]>b.a[i])flag=1;
              break;
            }
          }else{
            if(len>b.len)flag=1;
          }
          if(flag){
            for(i=1;i<=len;i++)c.a[i]=a[i];
            for(i=1;i<=b.len;i++)c.a[i]-=b.a[i];
            for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=B;
            while(c.len>1&&!c.a[c.len])c.len--;
            c.fu=fu;
          }else{
            for(i=1;i<=b.len;i++)c.a[i]=b.a[i];
            for(i=1;i<=len;i++)c.a[i]-=a[i];
            for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=B;
            while(c.len>1&&!c.a[c.len])c.len--;
            c.fu=b.fu;
          }
        }
        return c;
      }
      void write(){
        printf("%d",a[len]);
        for(int i=len-1;i;i--)printf("%04d",a[i]);
      }
      void set(int x){
        if(x<0){a[len=1]=fu=1;return;}
        fu=0,a[len=1]=x;
      }
    }num,sub;
    int main(){
      for(i=2;i<N;i++){
        if(!v[i])p[tot++]=i;
        for(j=0;j<tot&&i*p[j]<N;j++){
          v[i*p[j]]=1;
          if(i%p[j]==0)break;
        }
      }
      scanf("%d",&n);
      while(n--)divide();
      for(i=1;i<=cb;i++)solve(b[i]);
      sort(a+1,a+ca+1);
      for(i=1;i<=ca;i=j){
        for(j=i;j<=ca&&a[i]==a[j];j++);
        k=j-i,tot=a[i]<0?2:1;
        if(k>ans0)ans0=k,ans1=tot;else if(k==ans0)ans1+=tot;
      }
      printf("%d
    ",ans0);
      num.set(1);
      while(ans1--)num=num+num;
      sub.set(-1);
      num=num+sub;
      num.write();
      return 0;
    }
    

      

  • 相关阅读:
    Unity热更新04-XLua调用C#-01-Lua调用C#类
    Unity热更新03-C#调用XLua-010-LuaMgr
    Unity热更新03-C#调用XLua-09-Lua表映射到 XLua的LuaTable中(不建议)
    Unity热更新03-C#调用XLua-07-Lua表映射到C#接口
    Unity热更新03-C#调用XLua-07-Lua表映射到C#类
    C# 禁用控制台应用程序关闭按钮
    只允许输入正整数、负数、 控制小数点不能是第一位,负号必须第一位
    Godot
    GameFramework摘录
    GameFramework摘录
  • 原文地址:https://www.cnblogs.com/clrs97/p/5933357.html
Copyright © 2011-2022 走看看